Skip to content

Commit cb8ccd2

Browse files
jerrypengeolivelli
authored andcommitted
Improve error handling during localrun start (apache#10450)
1 parent 730941a commit cb8ccd2

File tree

1 file changed

+84
-72
lines changed
  • pulsar-functions/localrun/src/main/java/org/apache/pulsar/functions

1 file changed

+84
-72
lines changed

pulsar-functions/localrun/src/main/java/org/apache/pulsar/functions/LocalRunner.java

Lines changed: 84 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
import org.apache.pulsar.functions.instance.InstanceConfig;
6464
import org.apache.pulsar.functions.instance.stats.FunctionCollectorRegistry;
6565
import org.apache.pulsar.functions.proto.Function;
66+
import org.apache.pulsar.functions.runtime.RuntimeFactory;
6667
import org.apache.pulsar.functions.runtime.RuntimeSpawner;
6768
import org.apache.pulsar.functions.runtime.RuntimeUtils;
6869
import org.apache.pulsar.functions.runtime.process.ProcessRuntimeFactory;
@@ -94,6 +95,8 @@ public class LocalRunner implements AutoCloseable {
9495
private final Thread shutdownHook;
9596
private ClassLoader userCodeClassLoader;
9697
private boolean userCodeClassLoaderCreated;
98+
private RuntimeFactory runtimeFactory;
99+
private HTTPServer metricsServer;
97100

98101
public enum RuntimeEnv {
99102
THREAD,
@@ -185,7 +188,12 @@ public static void main(String[] args) throws Exception {
185188

186189
// parse args by JCommander
187190
jcommander.parse(args);
188-
localRunner.start(true);
191+
try {
192+
localRunner.start(true);
193+
} catch (Exception e) {
194+
log.error("Encountered error starting localrunner", e);
195+
localRunner.close();
196+
}
189197
}
190198

191199
@Builder
@@ -227,11 +235,13 @@ public LocalRunner(FunctionConfig functionConfig, SourceConfig sourceConfig, Sin
227235
this.connectorsDir = Paths.get(pulsarHome, "connectors").toString();
228236
}
229237
this.metricsPortStart = metricsPortStart;
230-
shutdownHook = new Thread() {
231-
public void run() {
232-
LocalRunner.this.stop();
238+
shutdownHook = new Thread(() -> {
239+
try {
240+
LocalRunner.this.close();
241+
} catch (Exception exception) {
242+
log.warn("Encountered exception when closing localrunner", exception);
233243
}
234-
};
244+
});
235245
}
236246

237247
private static File createNarExtractionTempDirectory() {
@@ -260,12 +270,21 @@ public synchronized void stop() {
260270
} catch (IllegalStateException e) {
261271
// ignore possible "Shutdown in progress"
262272
}
263-
log.info("Shutting down the localrun runtimeSpawner ...");
273+
274+
if (metricsServer != null) {
275+
metricsServer.stop();
276+
}
277+
264278
for (RuntimeSpawner spawner : spawners) {
265279
spawner.close();
266280
}
267281
spawners.clear();
268282

283+
if (runtimeFactory != null) {
284+
runtimeFactory.close();
285+
runtimeFactory = null;
286+
}
287+
269288
if (userCodeClassLoaderCreated) {
270289
if (userCodeClassLoader instanceof Closeable) {
271290
try {
@@ -464,7 +483,7 @@ private void startProcessMode(org.apache.pulsar.functions.proto.Function.Functio
464483
String stateStorageServiceUrl, AuthenticationConfig authConfig,
465484
String userCodeFile) throws Exception {
466485
SecretsProviderConfigurator secretsProviderConfigurator = getSecretsProviderConfigurator();
467-
try (ProcessRuntimeFactory containerFactory = new ProcessRuntimeFactory(
486+
runtimeFactory = new ProcessRuntimeFactory(
468487
serviceUrl,
469488
webServiceUrl,
470489
stateStorageServiceUrl,
@@ -475,71 +494,66 @@ private void startProcessMode(org.apache.pulsar.functions.proto.Function.Functio
475494
null, /* extra dependencies dir */
476495
narExtractionDirectory, /* nar extraction dir */
477496
secretsProviderConfigurator,
478-
false, Optional.empty(), Optional.empty())) {
479-
480-
for (int i = 0; i < parallelism; ++i) {
481-
InstanceConfig instanceConfig = new InstanceConfig();
482-
instanceConfig.setFunctionDetails(functionDetails);
483-
// TODO: correctly implement function version and id
484-
instanceConfig.setFunctionVersion(UUID.randomUUID().toString());
485-
instanceConfig.setFunctionId(UUID.randomUUID().toString());
486-
instanceConfig.setInstanceId(i + instanceIdOffset);
487-
instanceConfig.setMaxBufferedTuples(1024);
488-
instanceConfig.setPort(FunctionCommon.findAvailablePort());
489-
490-
if (metricsPortStart != null) {
491-
int metricsPort = metricsPortStart + i;
492-
if (metricsPortStart < 0 || metricsPortStart > 65535) {
493-
throw new IllegalArgumentException("Metrics port need to be within the range of 0 and 65535");
494-
}
495-
instanceConfig.setMetricsPort(metricsPort);
496-
} else {
497-
instanceConfig.setMetricsPort(FunctionCommon.findAvailablePort());
497+
false, Optional.empty(), Optional.empty());
498+
499+
for (int i = 0; i < parallelism; ++i) {
500+
InstanceConfig instanceConfig = new InstanceConfig();
501+
instanceConfig.setFunctionDetails(functionDetails);
502+
// TODO: correctly implement function version and id
503+
instanceConfig.setFunctionVersion(UUID.randomUUID().toString());
504+
instanceConfig.setFunctionId(UUID.randomUUID().toString());
505+
instanceConfig.setInstanceId(i + instanceIdOffset);
506+
instanceConfig.setMaxBufferedTuples(1024);
507+
instanceConfig.setPort(FunctionCommon.findAvailablePort());
508+
509+
if (metricsPortStart != null) {
510+
int metricsPort = metricsPortStart + i;
511+
if (metricsPortStart < 0 || metricsPortStart > 65535) {
512+
throw new IllegalArgumentException("Metrics port need to be within the range of 0 and 65535");
498513
}
499-
instanceConfig.setClusterName("local");
500-
if (functionConfig != null) {
501-
instanceConfig.setMaxPendingAsyncRequests(functionConfig.getMaxPendingAsyncRequests());
502-
if (functionConfig.getExposePulsarAdminClientEnabled() != null) {
503-
instanceConfig.setExposePulsarAdminClientEnabled(functionConfig.getExposePulsarAdminClientEnabled());
504-
}
514+
instanceConfig.setMetricsPort(metricsPort);
515+
} else {
516+
instanceConfig.setMetricsPort(FunctionCommon.findAvailablePort());
517+
}
518+
instanceConfig.setClusterName("local");
519+
if (functionConfig != null) {
520+
instanceConfig.setMaxPendingAsyncRequests(functionConfig.getMaxPendingAsyncRequests());
521+
if (functionConfig.getExposePulsarAdminClientEnabled() != null) {
522+
instanceConfig.setExposePulsarAdminClientEnabled(functionConfig.getExposePulsarAdminClientEnabled());
505523
}
506-
RuntimeSpawner runtimeSpawner = new RuntimeSpawner(
507-
instanceConfig,
508-
userCodeFile,
509-
null,
510-
containerFactory,
511-
30000);
512-
spawners.add(runtimeSpawner);
513-
runtimeSpawner.start();
514524
}
515-
Timer statusCheckTimer = new Timer();
516-
statusCheckTimer.scheduleAtFixedRate(new TimerTask() {
517-
@Override
518-
public void run() {
519-
CompletableFuture<String>[] futures = new CompletableFuture[spawners.size()];
520-
int index = 0;
521-
for (RuntimeSpawner spawner : spawners) {
522-
futures[index] = spawner.getFunctionStatusAsJson(index);
523-
index++;
524-
}
525-
try {
526-
CompletableFuture.allOf(futures).get(5, TimeUnit.SECONDS);
527-
for (index = 0; index < futures.length; ++index) {
528-
String json = futures[index].get();
529-
Gson gson = new GsonBuilder().setPrettyPrinting().create();
530-
log.info(gson.toJson(new JsonParser().parse(json)));
531-
}
532-
} catch (TimeoutException | InterruptedException | ExecutionException e) {
533-
log.error("Could not get status from all local instances");
534-
}
525+
RuntimeSpawner runtimeSpawner = new RuntimeSpawner(
526+
instanceConfig,
527+
userCodeFile,
528+
null,
529+
runtimeFactory,
530+
30000);
531+
spawners.add(runtimeSpawner);
532+
runtimeSpawner.start();
533+
}
534+
Timer statusCheckTimer = new Timer();
535+
statusCheckTimer.scheduleAtFixedRate(new TimerTask() {
536+
@Override
537+
public void run() {
538+
CompletableFuture<String>[] futures = new CompletableFuture[spawners.size()];
539+
int index = 0;
540+
for (RuntimeSpawner spawner : spawners) {
541+
futures[index] = spawner.getFunctionStatusAsJson(index);
542+
index++;
535543
}
536-
}, 30000, 30000);
537-
java.lang.Runtime.getRuntime().addShutdownHook(new Thread() {
538-
public void run() {
539-
statusCheckTimer.cancel();
544+
try {
545+
CompletableFuture.allOf(futures).get(5, TimeUnit.SECONDS);
546+
for (index = 0; index < futures.length; ++index) {
547+
String json = futures[index].get();
548+
Gson gson = new GsonBuilder().setPrettyPrinting().create();
549+
log.info(gson.toJson(new JsonParser().parse(json)));
550+
}
551+
} catch (TimeoutException | InterruptedException | ExecutionException e) {
552+
log.error("Could not get status from all local instances");
540553
}
541-
});
542-
}
554+
}
555+
}, 30000, 30000);
556+
java.lang.Runtime.getRuntime().addShutdownHook(new Thread(() -> statusCheckTimer.cancel()));
543557
}
544558

545559

@@ -574,13 +588,12 @@ private void startThreadedMode(org.apache.pulsar.functions.proto.Function.Functi
574588
FunctionCollectorRegistry collectorRegistry = FunctionCollectorRegistry.getDefaultImplementation();
575589
RuntimeUtils.registerDefaultCollectors(collectorRegistry);
576590

577-
ThreadRuntimeFactory threadRuntimeFactory;
578591
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
579592
try {
580593
if (userCodeClassLoader != null) {
581594
Thread.currentThread().setContextClassLoader(userCodeClassLoader);
582595
}
583-
threadRuntimeFactory = new ThreadRuntimeFactory("LocalRunnerThreadGroup",
596+
runtimeFactory = new ThreadRuntimeFactory("LocalRunnerThreadGroup",
584597
serviceUrl,
585598
stateStorageServiceUrl,
586599
authConfig,
@@ -614,16 +627,15 @@ private void startThreadedMode(org.apache.pulsar.functions.proto.Function.Functi
614627
instanceConfig,
615628
userCodeFile,
616629
null,
617-
threadRuntimeFactory,
630+
runtimeFactory,
618631
30000);
619632
spawners.add(runtimeSpawner);
620633
runtimeSpawner.start();
621634
}
622-
623635
if (metricsPortStart != null) {
624636
// starting metrics server
625637
log.info("Starting metrics server on port {}", metricsPortStart);
626-
new HTTPServer(new InetSocketAddress(metricsPortStart), collectorRegistry, true);
638+
metricsServer = new HTTPServer(new InetSocketAddress(metricsPortStart), collectorRegistry, true);
627639
}
628640
}
629641

0 commit comments

Comments
 (0)