Skip to content

Commit dd94ff8

Browse files
committed
fix: use resource version in watcher to get newest events from API.
This fixes [bug]: Deletion events seem to be missing after ResourceWatcher reconnect #675. Signed-off-by: Christoph Bühler <[email protected]>
1 parent e85cae5 commit dd94ff8

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

src/KubeOps.KubernetesClient/IKubernetesClient.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,10 @@ void Delete<TEntity>(string name, string? @namespace = null)
353353
/// If the namespace is omitted, all entities on the cluster are watched.
354354
/// </param>
355355
/// <param name="timeout">The timeout which the watcher has (after this timeout, the server will close the connection).</param>
356+
/// <param name="resourceVersion">
357+
/// When specified with a watch call, shows changes that occur after that particular version of a resource.
358+
/// Defaults to changes from the beginning of history.
359+
/// </param>
356360
/// <param name="cancellationToken">Cancellation-Token.</param>
357361
/// <param name="labelSelectors">A list of label-selectors to apply to the search.</param>
358362
/// <returns>A entity watcher for the given entity.</returns>
@@ -362,6 +366,7 @@ Watcher<TEntity> Watch<TEntity>(
362366
Action? onClose = null,
363367
string? @namespace = null,
364368
TimeSpan? timeout = null,
369+
string? resourceVersion = null,
365370
CancellationToken cancellationToken = default,
366371
params LabelSelector[] labelSelectors)
367372
where TEntity : IKubernetesObject<V1ObjectMeta>
@@ -371,6 +376,7 @@ Watcher<TEntity> Watch<TEntity>(
371376
onClose,
372377
@namespace,
373378
timeout,
379+
resourceVersion,
374380
labelSelectors.ToExpression(),
375381
cancellationToken);
376382

@@ -388,6 +394,10 @@ Watcher<TEntity> Watch<TEntity>(
388394
/// If the namespace is omitted, all entities on the cluster are watched.
389395
/// </param>
390396
/// <param name="timeout">The timeout which the watcher has (after this timeout, the server will close the connection).</param>
397+
/// <param name="resourceVersion">
398+
/// When specified with a watch call, shows changes that occur after that particular version of a resource.
399+
/// Defaults to changes from the beginning of history.
400+
/// </param>
391401
/// <param name="labelSelector">A string, representing an optional label selector for filtering watched objects.</param>
392402
/// <param name="cancellationToken">Cancellation-Token.</param>
393403
/// <returns>A entity watcher for the given entity.</returns>
@@ -397,6 +407,7 @@ Watcher<TEntity> Watch<TEntity>(
397407
Action? onClose = null,
398408
string? @namespace = null,
399409
TimeSpan? timeout = null,
410+
string? resourceVersion = null,
400411
string? labelSelector = null,
401412
CancellationToken cancellationToken = default)
402413
where TEntity : IKubernetesObject<V1ObjectMeta>;

src/KubeOps.KubernetesClient/KubernetesClient.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ public Watcher<TEntity> Watch<TEntity>(
295295
Action? onClose = null,
296296
string? @namespace = null,
297297
TimeSpan? timeout = null,
298+
string? resourceVersion = null,
298299
string? labelSelector = null,
299300
CancellationToken cancellationToken = default)
300301
where TEntity : IKubernetesObject<V1ObjectMeta>
@@ -308,6 +309,7 @@ public Watcher<TEntity> Watch<TEntity>(
308309
@namespace,
309310
metadata.PluralName,
310311
labelSelector: labelSelector,
312+
resourceVersion: resourceVersion,
311313
timeoutSeconds: timeout switch
312314
{
313315
null => null,
@@ -320,6 +322,7 @@ public Watcher<TEntity> Watch<TEntity>(
320322
metadata.Version,
321323
metadata.PluralName,
322324
labelSelector: labelSelector,
325+
resourceVersion: resourceVersion,
323326
timeoutSeconds: timeout switch
324327
{
325328
null => null,

src/KubeOps.Operator/Watcher/ResourceWatcher{TEntity}.cs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ internal class ResourceWatcher<TEntity> : IHostedService
3232
private uint _watcherReconnectRetries;
3333

3434
private Watcher<TEntity>? _watcher;
35+
private string? _lastResourceVersion;
3536

3637
public ResourceWatcher(
3738
ILogger<ResourceWatcher<TEntity>> logger,
@@ -82,7 +83,12 @@ private void WatchResource()
8283
}
8384

8485
_logger.LogDebug("""Create watcher for entity of type "{type}".""", typeof(TEntity));
85-
_watcher = _client.Watch<TEntity>(OnEvent, OnError, OnClosed, @namespace: _settings.Namespace);
86+
_watcher = _client.Watch<TEntity>(
87+
OnEvent,
88+
OnError,
89+
OnClosed,
90+
@namespace: _settings.Namespace,
91+
resourceVersion: _lastResourceVersion);
8692
}
8793

8894
private void StopWatching()
@@ -158,12 +164,14 @@ private void OnClosed()
158164
private async void OnEvent(WatchEventType type, TEntity entity)
159165
{
160166
_watcherReconnectRetries = 0;
167+
_lastResourceVersion = entity.ResourceVersion();
161168

162169
_logger.LogTrace(
163-
"""Received watch event "{eventType}" for "{kind}/{name}".""",
170+
"""Received watch event "{eventType}" for "{kind}/{name}", last observed resource version: {resourceVersion}.""",
164171
type,
165172
entity.Kind,
166-
entity.Name());
173+
entity.Name(),
174+
_lastResourceVersion);
167175

168176
_queue.RemoveIfQueued(entity);
169177

0 commit comments

Comments
 (0)