@@ -71,6 +71,8 @@ public final class SimplePluginBuilder {
7171 private final List <Consumer <WorkerFactoryOptions .Builder >> factoryCustomizers = new ArrayList <>();
7272 private final List <Consumer <WorkerOptions .Builder >> workerCustomizers = new ArrayList <>();
7373 private final List <BiConsumer <String , Worker >> workerInitializers = new ArrayList <>();
74+ private final List <BiConsumer <String , Worker >> workerStartCallbacks = new ArrayList <>();
75+ private final List <BiConsumer <String , Worker >> workerShutdownCallbacks = new ArrayList <>();
7476 private final List <WorkerInterceptor > workerInterceptors = new ArrayList <>();
7577 private final List <WorkflowClientInterceptor > clientInterceptors = new ArrayList <>();
7678 private final List <ContextPropagator > contextPropagators = new ArrayList <>();
@@ -164,6 +166,59 @@ public SimplePluginBuilder initializeWorker(@Nonnull BiConsumer<String, Worker>
164166 return this ;
165167 }
166168
169+ /**
170+ * Adds a callback that is invoked when a worker starts. This can be used to start per-worker
171+ * resources or record metrics.
172+ *
173+ * <p>Note: For registering workflows and activities, use {@link #initializeWorker} instead, as
174+ * registrations must happen before the worker starts polling.
175+ *
176+ * <p>Example:
177+ *
178+ * <pre>{@code
179+ * SimplePluginBuilder.newBuilder("my-plugin")
180+ * .onWorkerStart((taskQueue, worker) -> {
181+ * logger.info("Worker started for task queue: {}", taskQueue);
182+ * perWorkerResources.put(taskQueue, new ResourcePool());
183+ * })
184+ * .build();
185+ * }</pre>
186+ *
187+ * @param callback a consumer that receives the task queue name and worker when the worker starts
188+ * @return this builder for chaining
189+ */
190+ public SimplePluginBuilder onWorkerStart (@ Nonnull BiConsumer <String , Worker > callback ) {
191+ workerStartCallbacks .add (Objects .requireNonNull (callback ));
192+ return this ;
193+ }
194+
195+ /**
196+ * Adds a callback that is invoked when a worker shuts down. This can be used to clean up
197+ * per-worker resources initialized in {@link #initializeWorker} or {@link #onWorkerStart}.
198+ *
199+ * <p>Example:
200+ *
201+ * <pre>{@code
202+ * SimplePluginBuilder.newBuilder("my-plugin")
203+ * .onWorkerShutdown((taskQueue, worker) -> {
204+ * logger.info("Worker shutting down for task queue: {}", taskQueue);
205+ * ResourcePool pool = perWorkerResources.remove(taskQueue);
206+ * if (pool != null) {
207+ * pool.close();
208+ * }
209+ * })
210+ * .build();
211+ * }</pre>
212+ *
213+ * @param callback a consumer that receives the task queue name and worker when the worker shuts
214+ * down
215+ * @return this builder for chaining
216+ */
217+ public SimplePluginBuilder onWorkerShutdown (@ Nonnull BiConsumer <String , Worker > callback ) {
218+ workerShutdownCallbacks .add (Objects .requireNonNull (callback ));
219+ return this ;
220+ }
221+
167222 /**
168223 * Adds worker interceptors. Interceptors are appended to any existing interceptors in the
169224 * configuration.
@@ -214,6 +269,8 @@ public PluginBase build() {
214269 new ArrayList <>(factoryCustomizers ),
215270 new ArrayList <>(workerCustomizers ),
216271 new ArrayList <>(workerInitializers ),
272+ new ArrayList <>(workerStartCallbacks ),
273+ new ArrayList <>(workerShutdownCallbacks ),
217274 new ArrayList <>(workerInterceptors ),
218275 new ArrayList <>(clientInterceptors ),
219276 new ArrayList <>(contextPropagators ));
@@ -226,6 +283,8 @@ private static final class SimplePlugin extends PluginBase {
226283 private final List <Consumer <WorkerFactoryOptions .Builder >> factoryCustomizers ;
227284 private final List <Consumer <WorkerOptions .Builder >> workerCustomizers ;
228285 private final List <BiConsumer <String , Worker >> workerInitializers ;
286+ private final List <BiConsumer <String , Worker >> workerStartCallbacks ;
287+ private final List <BiConsumer <String , Worker >> workerShutdownCallbacks ;
229288 private final List <WorkerInterceptor > workerInterceptors ;
230289 private final List <WorkflowClientInterceptor > clientInterceptors ;
231290 private final List <ContextPropagator > contextPropagators ;
@@ -237,6 +296,8 @@ private static final class SimplePlugin extends PluginBase {
237296 List <Consumer <WorkerFactoryOptions .Builder >> factoryCustomizers ,
238297 List <Consumer <WorkerOptions .Builder >> workerCustomizers ,
239298 List <BiConsumer <String , Worker >> workerInitializers ,
299+ List <BiConsumer <String , Worker >> workerStartCallbacks ,
300+ List <BiConsumer <String , Worker >> workerShutdownCallbacks ,
240301 List <WorkerInterceptor > workerInterceptors ,
241302 List <WorkflowClientInterceptor > clientInterceptors ,
242303 List <ContextPropagator > contextPropagators ) {
@@ -246,6 +307,8 @@ private static final class SimplePlugin extends PluginBase {
246307 this .factoryCustomizers = factoryCustomizers ;
247308 this .workerCustomizers = workerCustomizers ;
248309 this .workerInitializers = workerInitializers ;
310+ this .workerStartCallbacks = workerStartCallbacks ;
311+ this .workerShutdownCallbacks = workerShutdownCallbacks ;
249312 this .workerInterceptors = workerInterceptors ;
250313 this .clientInterceptors = clientInterceptors ;
251314 this .contextPropagators = contextPropagators ;
@@ -328,5 +391,24 @@ public void initializeWorker(@Nonnull String taskQueue, @Nonnull Worker worker)
328391 initializer .accept (taskQueue , worker );
329392 }
330393 }
394+
395+ @ Override
396+ public void startWorker (
397+ @ Nonnull String taskQueue , @ Nonnull Worker worker , @ Nonnull Runnable next )
398+ throws Exception {
399+ next .run ();
400+ for (BiConsumer <String , Worker > callback : workerStartCallbacks ) {
401+ callback .accept (taskQueue , worker );
402+ }
403+ }
404+
405+ @ Override
406+ public void shutdownWorker (
407+ @ Nonnull String taskQueue , @ Nonnull Worker worker , @ Nonnull Runnable next ) {
408+ for (BiConsumer <String , Worker > callback : workerShutdownCallbacks ) {
409+ callback .accept (taskQueue , worker );
410+ }
411+ next .run ();
412+ }
331413 }
332414}
0 commit comments