-
Notifications
You must be signed in to change notification settings - Fork 44
feat: add workflow client updater for updating workflow client #258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| using System; | ||
| using Temporalio.Worker; | ||
|
|
||
| namespace Temporalio.Extensions.Hosting | ||
| { | ||
| /// <summary> | ||
| /// Subscribes to the <see cref="TemporalWorkerClientUpdater"/>, and propagates the worker client changes to the Temporal worker. | ||
| /// </summary> | ||
| public class TemporalWorkerClientUpdateSubscriber : IDisposable | ||
| { | ||
| private readonly TemporalWorkerClientUpdater temporalWorkerClientUpdater; | ||
| private readonly TemporalWorker worker; | ||
| private bool disposedValue; | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="TemporalWorkerClientUpdateSubscriber"/> class. | ||
| /// </summary> | ||
| /// <param name="temporalWorkerClientUpdater">The optional <see cref="TemporalWorkerClientUpdater"/> used to subscribe to updates.</param> | ||
| /// <param name="worker">The <see cref="TemporalWorker"/> that will be updated when the worker client updates.</param> | ||
| public TemporalWorkerClientUpdateSubscriber( | ||
| TemporalWorkerClientUpdater temporalWorkerClientUpdater, | ||
| TemporalWorker worker) | ||
| { | ||
| this.temporalWorkerClientUpdater = temporalWorkerClientUpdater; | ||
| this.worker = worker; | ||
| this.temporalWorkerClientUpdater.TemporalWorkerClientUpdated += OnTemporalWorkerClientUpdated; | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Finalizes an instance of the <see cref="TemporalWorkerClientUpdateSubscriber"/> class. | ||
| /// </summary> | ||
| ~TemporalWorkerClientUpdateSubscriber() => Dispose(false); | ||
|
|
||
| /// <inheritdoc/> | ||
| public void Dispose() | ||
| { | ||
| Dispose(true); | ||
| GC.SuppressFinalize(this); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Unsubscribes from the worker client updater if one exists. | ||
| /// </summary> | ||
| /// <param name="disposing">If set to <see langword="true"/>, the worker will unsubscribe from the worker client updater.</param> | ||
| protected virtual void Dispose(bool disposing) | ||
| { | ||
| if (!disposedValue) | ||
| { | ||
| if (disposing) | ||
| { | ||
| temporalWorkerClientUpdater.TemporalWorkerClientUpdated -= OnTemporalWorkerClientUpdated; | ||
| } | ||
|
|
||
| disposedValue = true; | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Callback invoked when a worker client updated is pushed through the <see cref="TemporalWorkerClientUpdater"/>. | ||
| /// </summary> | ||
| /// <param name="sender">The sender of the event.</param> | ||
| /// <param name="eventArgs">The <see cref="TemporalWorkerClientUpdatedEventArgs"/> of the event.</param> | ||
| private void OnTemporalWorkerClientUpdated(object? sender, TemporalWorkerClientUpdatedEventArgs eventArgs) | ||
| { | ||
| worker.Client = eventArgs.WorkerClient; | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| using System; | ||
| using Temporalio.Worker; | ||
|
|
||
| namespace Temporalio.Extensions.Hosting | ||
| { | ||
| /// <summary> | ||
| /// Event raised when a worker client is updated. | ||
| /// </summary> | ||
| public class TemporalWorkerClientUpdatedEventArgs : EventArgs | ||
| { | ||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="TemporalWorkerClientUpdatedEventArgs"/> class. | ||
| /// </summary> | ||
| /// <param name="workerClient">The client to update workers with.</param> | ||
| public TemporalWorkerClientUpdatedEventArgs(IWorkerClient workerClient) => WorkerClient = workerClient; | ||
|
|
||
| /// <summary> | ||
| /// Gets the <see cref="IWorkerClient"/> that will be propagated to all event listeners. | ||
| /// </summary> | ||
| public IWorkerClient WorkerClient { get; } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| using System; | ||
| using Temporalio.Worker; | ||
|
|
||
| namespace Temporalio.Extensions.Hosting | ||
| { | ||
| /// <summary> | ||
| /// Notification hub that can be used to push Temporal worker client updates to subscribing Temporal workers. | ||
| /// </summary> | ||
| public class TemporalWorkerClientUpdater | ||
| { | ||
| private readonly object clientLock = new(); | ||
|
|
||
| /// <summary> | ||
| /// The <see cref="EventHandler"/> used to dispatch notifications to subscribers that the Temporal worker client was updated. | ||
| /// </summary> | ||
| public event EventHandler<TemporalWorkerClientUpdatedEventArgs> TemporalWorkerClientUpdated | ||
robcao marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| add | ||
| { | ||
| lock (clientLock) | ||
| { | ||
| TemporalWorkerClientUpdatedEvent += value; | ||
| } | ||
| } | ||
|
|
||
| remove | ||
| { | ||
| lock (clientLock) | ||
| { | ||
| TemporalWorkerClientUpdatedEvent -= value; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private event EventHandler<TemporalWorkerClientUpdatedEventArgs>? TemporalWorkerClientUpdatedEvent; | ||
|
|
||
| /// <summary> | ||
| /// Dispatches a notification to all subscribers that a new worker client should be used. | ||
| /// </summary> | ||
| /// <param name="client">The new <see cref="IWorkerClient"/> that should be pushed out to all subscribing workers.</param> | ||
| public void UpdateTemporalWorkerClient(IWorkerClient client) | ||
robcao marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| TemporalWorkerClientUpdatedEventArgs eventArgs = new TemporalWorkerClientUpdatedEventArgs(client); | ||
|
|
||
| TemporalWorkerClientUpdatedEvent?.Invoke(this, eventArgs); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,6 +19,7 @@ public class TemporalWorkerService : BackgroundService | |||||||||||||
| private readonly TemporalClientConnectOptions? newClientOptions; | ||||||||||||||
| private readonly ITemporalClient? existingClient; | ||||||||||||||
| private readonly TemporalWorkerOptions workerOptions; | ||||||||||||||
| private readonly TemporalWorkerClientUpdater? workerClientUpdater; | ||||||||||||||
|
Comment on lines
19
to
+22
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Now that we are basically storing the three separate pieces anyways, let's just store the full service options as one field
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's not really a good way I've found to handle the constructors that take in I don't know of a better way to convert an instance of I think it would be easier if
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I see now that we have multiple constructors for this |
||||||||||||||
|
|
||||||||||||||
| /// <summary> | ||||||||||||||
| /// Initializes a new instance of the <see cref="TemporalWorkerService"/> class using | ||||||||||||||
|
|
@@ -157,6 +158,11 @@ public TemporalWorkerService( | |||||||||||||
| { | ||||||||||||||
| newClientOptions.LoggerFactory = workerOptions.LoggerFactory; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| if (options.WorkerClientUpdater != null) | ||||||||||||||
| { | ||||||||||||||
| this.workerClientUpdater = options.WorkerClientUpdater; | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /// <inheritdoc /> | ||||||||||||||
|
|
@@ -166,7 +172,18 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) | |||||||||||||
| // Call connect just in case it was a lazy client (no-op if already connected) | ||||||||||||||
| await client.Connection.ConnectAsync().ConfigureAwait(false); | ||||||||||||||
| using var worker = new TemporalWorker(client, workerOptions); | ||||||||||||||
| await worker.ExecuteAsync(stoppingToken).ConfigureAwait(false); | ||||||||||||||
|
|
||||||||||||||
| if (workerClientUpdater != null) | ||||||||||||||
| { | ||||||||||||||
| using (new TemporalWorkerClientUpdateSubscriber(workerClientUpdater, worker)) | ||||||||||||||
| { | ||||||||||||||
| await worker.ExecuteAsync(stoppingToken).ConfigureAwait(false); | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| else | ||||||||||||||
| { | ||||||||||||||
| await worker.ExecuteAsync(stoppingToken).ConfigureAwait(false); | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.