Skip to content

Commit f966971

Browse files
authored
Merge pull request #333 from code-dot-org/molly/global-context-part-2
Part 2 of adding global context
2 parents 0db864c + ec29ec8 commit f966971

28 files changed

+126
-244
lines changed

org-code-javabuilder/lib/src/main/java/dev/javabuilder/LocalMetricClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package dev.javabuilder;
22

3+
import org.code.protocol.JavabuilderSharedObject;
34
import org.code.protocol.MetricClient;
45

56
// Local implementation of MetricClient. Since all we can do locally
67
// is log and we already have regular logging for every metric,
78
// these methods do nothing.
8-
public class LocalMetricClient implements MetricClient {
9+
public class LocalMetricClient extends JavabuilderSharedObject implements MetricClient {
910
@Override
1011
public void publishSevereError() {}
1112

org-code-javabuilder/lib/src/main/java/dev/javabuilder/LocalSystemExitHelper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@
22

33
import org.code.javabuilder.PerformanceTracker;
44
import org.code.javabuilder.SystemExitHelper;
5+
import org.code.protocol.JavabuilderContext;
56

67
public class LocalSystemExitHelper implements SystemExitHelper {
78

89
@Override
910
public void exit(int status) {
10-
PerformanceTracker.getInstance().trackInstanceEnd();
11-
PerformanceTracker.getInstance().logPerformance();
11+
PerformanceTracker performanceTracker =
12+
(PerformanceTracker) JavabuilderContext.getInstance().get(PerformanceTracker.class);
13+
performanceTracker.trackInstanceEnd();
14+
performanceTracker.logPerformance();
1215
System.exit(status);
1316
}
1417
}

org-code-javabuilder/lib/src/main/java/dev/javabuilder/WebSocketServer.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,18 @@ public WebSocketServer() {
5454
public void onOpen(Session session) {
5555
this.finishedExecution = false;
5656
JavabuilderContext.getInstance().destroyAndReset();
57-
PerformanceTracker.resetTracker();
58-
PerformanceTracker.getInstance().trackInstanceStart(Clock.systemUTC().instant());
57+
PerformanceTracker performanceTracker = new PerformanceTracker();
58+
JavabuilderContext.getInstance().register(PerformanceTracker.class, performanceTracker);
59+
performanceTracker.trackInstanceStart(Clock.systemUTC().instant());
5960
// Decode the authorization token
6061
String token = session.getRequestParameterMap().get("Authorization").get(0);
6162
Base64.Decoder decoder = Base64.getDecoder();
6263
String payload = new String(decoder.decode(token.split("\\.")[1]));
6364
JSONObject queryInput = new JSONObject(payload);
6465

6566
final String connectionId = "LocalhostWebSocketConnection";
66-
final String levelId = queryInput.getString("level_id");
67+
final String levelId =
68+
queryInput.has("level_id") ? String.valueOf(queryInput.getInt("level_id")) : "noneProvided";
6769
final String channelId =
6870
queryInput.has("channel_id") ? queryInput.getString("channel_id") : "noneProvided";
6971
final ExecutionType executionType =
@@ -77,8 +79,8 @@ public void onOpen(Session session) {
7779
// turn off the default console logger
7880
this.logger.setUseParentHandlers(false);
7981

80-
MetricClient metricClient = new LocalMetricClient();
81-
MetricClientManager.create(metricClient);
82+
LocalMetricClient metricClient = new LocalMetricClient();
83+
JavabuilderContext.getInstance().register(MetricClient.class, metricClient);
8284

8385
Properties.setConnectionId(connectionId);
8486

@@ -89,7 +91,6 @@ public void onOpen(Session session) {
8991
if (executionType == ExecutionType.TEST) {
9092
outputAdapter = new UserTestOutputAdapter(websocketOutputAdapter);
9193
}
92-
final LifecycleNotifier lifecycleNotifier = new LifecycleNotifier();
9394

9495
final ExceptionHandler exceptionHandler =
9596
new ExceptionHandler(outputAdapter, new LocalSystemExitHelper());
@@ -108,7 +109,6 @@ public void onOpen(Session session) {
108109
compileList,
109110
new LocalTempDirectoryManager(),
110111
contentManager,
111-
lifecycleNotifier,
112112
new LocalSystemExitHelper());
113113
codeExecutionManager.execute();
114114
} catch (Throwable e) {
@@ -134,14 +134,17 @@ public void onOpen(Session session) {
134134
@OnClose
135135
public void myOnClose() {
136136
Logger.getLogger(MAIN_LOGGER).info("WebSocket closed.");
137-
PerformanceTracker.getInstance().logPerformance();
137+
PerformanceTracker performanceTracker =
138+
(PerformanceTracker) JavabuilderContext.getInstance().get(PerformanceTracker.class);
139+
performanceTracker.logPerformance();
138140
// If the websocket was closed before execution was finished, make sure we clean up.
139141
if (!this.finishedExecution) {
140142
if (codeExecutionManager != null) {
141143
this.codeExecutionManager.shutDown();
142144
}
143145
this.logger.removeHandler(this.logHandler);
144146
}
147+
JavabuilderContext.getInstance().destroyAndReset();
145148
}
146149

147150
/**

org-code-javabuilder/lib/src/main/java/org/code/javabuilder/AWSMetricClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
import com.amazonaws.services.cloudwatch.AmazonCloudWatch;
44
import com.amazonaws.services.cloudwatch.AmazonCloudWatchClientBuilder;
55
import com.amazonaws.services.cloudwatch.model.*;
6+
import org.code.protocol.JavabuilderSharedObject;
67
import org.code.protocol.MetricClient;
78

89
// Metric Client which published metrics to AWS CloudWatch.
910
// Requires cloudwatch:PutMetricData permission on the Lambda.
10-
public class AWSMetricClient implements MetricClient {
11+
public class AWSMetricClient extends JavabuilderSharedObject implements MetricClient {
1112
private final AmazonCloudWatch cloudWatchClient;
1213
private final Dimension functionNameDimension;
1314

org-code-javabuilder/lib/src/main/java/org/code/javabuilder/AWSSystemExitHelper.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.amazonaws.services.apigatewaymanagementapi.model.GoneException;
88
import java.util.logging.Handler;
99
import java.util.logging.Logger;
10+
import org.code.protocol.JavabuilderContext;
1011

1112
public class AWSSystemExitHelper implements SystemExitHelper {
1213
private final String connectionId;
@@ -19,8 +20,10 @@ public AWSSystemExitHelper(String connectionId, AmazonApiGatewayManagementApi ap
1920

2021
@Override
2122
public void exit(int status) {
22-
PerformanceTracker.getInstance().trackInstanceEnd();
23-
PerformanceTracker.getInstance().logPerformance();
23+
PerformanceTracker performanceTracker =
24+
(PerformanceTracker) JavabuilderContext.getInstance().get(PerformanceTracker.class);
25+
performanceTracker.trackInstanceEnd();
26+
performanceTracker.logPerformance();
2427
this.cleanUpResources();
2528
System.exit(status);
2629
}

org-code-javabuilder/lib/src/main/java/org/code/javabuilder/CodeExecutionManager.java

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public class CodeExecutionManager {
2323
private final ExecutionType executionType;
2424
private final List<String> compileList;
2525
private final TempDirectoryManager tempDirectoryManager;
26-
private final LifecycleNotifier lifecycleNotifier;
2726
private final ContentManager contentManager;
2827
private final SystemExitHelper systemExitHelper;
2928
private final CodeBuilderRunnableFactory codeBuilderRunnableFactory;
@@ -53,7 +52,6 @@ public CodeExecutionManager(
5352
List<String> compileList,
5453
TempDirectoryManager tempDirectoryManager,
5554
ContentManager contentManager,
56-
LifecycleNotifier lifecycleNotifier,
5755
SystemExitHelper systemExitHelper) {
5856
this(
5957
fileLoader,
@@ -62,7 +60,6 @@ public CodeExecutionManager(
6260
executionType,
6361
compileList,
6462
tempDirectoryManager,
65-
lifecycleNotifier,
6663
contentManager,
6764
systemExitHelper,
6865
new CodeBuilderRunnableFactory());
@@ -75,7 +72,6 @@ public CodeExecutionManager(
7572
ExecutionType executionType,
7673
List<String> compileList,
7774
TempDirectoryManager tempDirectoryManager,
78-
LifecycleNotifier lifecycleNotifier,
7975
ContentManager contentManager,
8076
SystemExitHelper systemExitHelper,
8177
CodeBuilderRunnableFactory codeBuilderRunnableFactory) {
@@ -85,7 +81,6 @@ public CodeExecutionManager(
8581
this.executionType = executionType;
8682
this.compileList = compileList;
8783
this.tempDirectoryManager = tempDirectoryManager;
88-
this.lifecycleNotifier = lifecycleNotifier;
8984
this.contentManager = contentManager;
9085
this.systemExitHelper = systemExitHelper;
9186
this.codeBuilderRunnableFactory = codeBuilderRunnableFactory;
@@ -127,10 +122,7 @@ private void onPreExecute() throws InternalServerException {
127122
// Create the Global Protocol instance
128123
GlobalProtocol protocolInstance =
129124
new GlobalProtocol(
130-
this.outputAdapter,
131-
new InputHandler(this.inputAdapter),
132-
this.lifecycleNotifier,
133-
this.contentManager);
125+
this.outputAdapter, new InputHandler(this.inputAdapter), this.contentManager);
134126
JavabuilderContext.getInstance().register(GlobalProtocol.class, protocolInstance);
135127

136128
// Create temp folder
@@ -152,14 +144,12 @@ private void onPreExecute() throws InternalServerException {
152144

153145
/**
154146
* Post-execution steps: 1) Notify listeners, 2) clean up global resources, 3) clear temporary
155-
* folder, 4) close custom in/out streams, 5) Replace System.in/out with original in/out, 6)
156-
* Destroy Global Protocol
147+
* folder, 4) close custom in/out streams, 5) Replace System.in/out with original in/out
157148
*/
158149
private void onPostExecute() {
159150
// Notify user and listeners
160151
LambdaUtils.safelySendMessage(
161152
this.outputAdapter, new StatusMessage(StatusMessageKey.EXITED), false);
162-
this.lifecycleNotifier.onExecutionEnded();
163153
JavabuilderContext.getInstance().onExecutionEnded();
164154
try {
165155
// Close custom input/output streams
@@ -174,10 +164,9 @@ private void onPostExecute() {
174164
LoggerUtils.logTrackingException(e);
175165
this.systemExitHelper.exit(TEMP_DIRECTORY_CLEANUP_ERROR_CODE);
176166
} finally {
177-
// Replace System in/out with original System in/out and reset JavabuilderContext
167+
// Replace System in/out with original System in/out
178168
System.setIn(this.systemInputStream);
179169
System.setOut(this.systemOutputStream);
180-
JavabuilderContext.getInstance().destroyAndReset();
181170
this.isInitialized = false;
182171
}
183172
}

org-code-javabuilder/lib/src/main/java/org/code/javabuilder/JavaRunner.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66
import java.util.List;
77
import java.util.stream.Collectors;
88
import org.code.javabuilder.util.JarUtils;
9-
import org.code.protocol.JavabuilderException;
10-
import org.code.protocol.OutputAdapter;
11-
import org.code.protocol.StatusMessage;
12-
import org.code.protocol.StatusMessageKey;
9+
import org.code.protocol.*;
1310

1411
/** The class that executes the student's code */
1512
public class JavaRunner {
@@ -93,11 +90,13 @@ private boolean run(
9390
classLoaderUrls, JavaRunner.class.getClassLoader(), classNames, permissionLevel);
9491

9592
boolean runResult;
96-
PerformanceTracker.getInstance().trackUserCodeStart();
93+
PerformanceTracker performanceTracker =
94+
(PerformanceTracker) JavabuilderContext.getInstance().get(PerformanceTracker.class);
95+
performanceTracker.trackUserCodeStart();
9796
try {
9897
runResult = runner.run(urlClassLoader);
9998
} finally {
100-
PerformanceTracker.getInstance().trackUserCodeEnd();
99+
performanceTracker.trackUserCodeEnd();
101100
}
102101

103102
try {

org-code-javabuilder/lib/src/main/java/org/code/javabuilder/LambdaRequestHandler.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ public LambdaRequestHandler() {
9898
@Override
9999
public String handleRequest(Map<String, String> lambdaInput, Context context) {
100100
this.isSessionInitialized = false;
101-
this.trackStartupPerformance();
102101
JavabuilderContext.getInstance().destroyAndReset();
102+
this.trackStartupPerformance();
103103

104104
// TODO: Because we reference the logger object throughout the codebase via
105105
// Logger.getLogger(MAIN_LOGGER), we need to set it up in the same scope as code execution to
@@ -181,8 +181,8 @@ private void initialize(Map<String, String> lambdaInput, String connectionId, Co
181181

182182
Properties.setConnectionId(connectionId);
183183

184-
MetricClient metricClient = new AWSMetricClient(context.getFunctionName());
185-
MetricClientManager.create(metricClient);
184+
AWSMetricClient metricClient = new AWSMetricClient(context.getFunctionName());
185+
JavabuilderContext.getInstance().register(MetricClient.class, metricClient);
186186

187187
// Dashboard assets are only accessible if the dashboard domain is not localhost
188188
Properties.setCanAccessDashboardAssets(canAccessDashboardAssets);
@@ -196,12 +196,13 @@ private void initialize(Map<String, String> lambdaInput, String connectionId, Co
196196

197197
private void trackStartupPerformance() {
198198
final Instant instanceStart = Clock.systemUTC().instant();
199-
PerformanceTracker.resetTracker();
199+
PerformanceTracker performanceTracker = new PerformanceTracker();
200+
JavabuilderContext.getInstance().register(PerformanceTracker.class, performanceTracker);
200201
if (coldBoot) {
201-
PerformanceTracker.getInstance().trackColdBoot(COLD_BOOT_START, COLD_BOOT_END, instanceStart);
202+
performanceTracker.trackColdBoot(COLD_BOOT_START, COLD_BOOT_END, instanceStart);
202203
coldBoot = false;
203204
} else {
204-
PerformanceTracker.getInstance().trackInstanceStart(instanceStart);
205+
performanceTracker.trackInstanceStart(instanceStart);
205206
}
206207
}
207208

@@ -260,7 +261,6 @@ private CodeExecutionManager createExecutionManager(
260261
final List<String> compileList = JSONUtils.listFromJSONObjectMember(options, "compileList");
261262

262263
final AWSInputAdapter inputAdapter = new AWSInputAdapter(SQS_CLIENT, queueUrl, queueName);
263-
final LifecycleNotifier lifecycleNotifier = new LifecycleNotifier();
264264
final AWSContentManager contentManager =
265265
new AWSContentManager(
266266
S3_CLIENT, CONTENT_BUCKET_NAME, javabuilderSessionId, CONTENT_BUCKET_URL, context);
@@ -273,7 +273,6 @@ private CodeExecutionManager createExecutionManager(
273273
compileList,
274274
tempDirectoryManager,
275275
contentManager,
276-
lifecycleNotifier,
277276
new AWSSystemExitHelper(connectionId, API_CLIENT));
278277
}
279278

@@ -303,8 +302,11 @@ private void shutDown(
303302
}
304303
}
305304

306-
PerformanceTracker.getInstance().trackInstanceEnd();
307-
PerformanceTracker.getInstance().logPerformance();
305+
PerformanceTracker performanceTracker =
306+
(PerformanceTracker) JavabuilderContext.getInstance().get(PerformanceTracker.class);
307+
performanceTracker.trackInstanceEnd();
308+
performanceTracker.logPerformance();
309+
JavabuilderContext.getInstance().destroyAndReset();
308310

309311
this.cleanUpAWSResources(connectionId, api);
310312

org-code-javabuilder/lib/src/main/java/org/code/javabuilder/PerformanceTracker.java

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
import java.time.Clock;
66
import java.time.Instant;
77
import java.util.logging.Logger;
8-
import org.code.protocol.LoggerConstants;
9-
import org.code.protocol.MetricClient;
10-
import org.code.protocol.MetricClientManager;
8+
import org.code.protocol.*;
119
import org.json.JSONObject;
1210

1311
/**
@@ -19,7 +17,7 @@
1917
* Then, at the end of the project execution, PerformanceTracker.logPerformance can be invoked in
2018
* order to create a single record of the performance of the project execution.
2119
*/
22-
public class PerformanceTracker {
20+
public class PerformanceTracker extends JavabuilderSharedObject {
2321
private static final String FIRST_INSTANCE = "firstInstance";
2422
private static final String COLD_BOOT_START = "coldBootStart";
2523
private static final String COLD_BOOT_END = "coldBootEnd";
@@ -35,25 +33,11 @@ public class PerformanceTracker {
3533
private static final String CLEANUP_TIME = "cleanupTime";
3634
private static final String TYPE = "performanceReport";
3735
private final JSONObject logs;
38-
private static PerformanceTracker instance;
3936

40-
private PerformanceTracker() {
37+
public PerformanceTracker() {
4138
this.logs = new JSONObject();
4239
}
4340

44-
public static PerformanceTracker getInstance() {
45-
if (PerformanceTracker.instance == null) {
46-
PerformanceTracker.instance = new PerformanceTracker();
47-
}
48-
49-
return PerformanceTracker.instance;
50-
}
51-
52-
/** Clear out all previous performance logs */
53-
public static void resetTracker() {
54-
PerformanceTracker.instance = new PerformanceTracker();
55-
}
56-
5741
public void trackColdBoot(Instant coldBootStart, Instant coldBootEnd, Instant instanceStart) {
5842
logs.put(COLD_BOOT_START, coldBootStart.toEpochMilli());
5943
logs.put(COLD_BOOT_END, coldBootEnd.toEpochMilli());
@@ -93,7 +77,8 @@ public void trackInstanceEnd() {
9377

9478
public void logPerformance() {
9579
logs.put(LoggerConstants.TYPE, TYPE);
96-
MetricClient metricClient = MetricClientManager.getInstance().getMetricClient();
80+
MetricClient metricClient =
81+
(MetricClient) JavabuilderContext.getInstance().get(MetricClient.class);
9782
if (!logs.isNull(COLD_BOOT_START) && !logs.isNull(COLD_BOOT_END)) {
9883
long coldBootTime = logs.getLong(COLD_BOOT_END) - logs.getLong(COLD_BOOT_START);
9984
logs.put(COLD_BOOT_TIME, coldBootTime);
@@ -119,6 +104,5 @@ public void logPerformance() {
119104
}
120105

121106
Logger.getLogger(MAIN_LOGGER).info(logs.toString());
122-
PerformanceTracker.instance = null;
123107
}
124108
}

org-code-javabuilder/lib/src/main/java/org/code/javabuilder/UserCodeCompiler.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@ public void compileProgram() throws InternalServerException, UserInitiatedExcept
4242
this.outputAdapter.sendMessage(new StatusMessage(StatusMessageKey.COMPILING));
4343
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
4444

45-
PerformanceTracker.getInstance().trackCompileStart();
45+
PerformanceTracker performanceTracker =
46+
(PerformanceTracker) JavabuilderContext.getInstance().get(PerformanceTracker.class);
47+
performanceTracker.trackCompileStart();
4648
CompilationTask task = getCompilationTask(diagnostics);
4749

4850
boolean success = task.call();
49-
PerformanceTracker.getInstance().trackCompileEnd();
51+
performanceTracker.trackCompileEnd();
5052

5153
// diagnostics will include any compiler errors
5254
for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {

0 commit comments

Comments
 (0)