Skip to content

Commit 0e65443

Browse files
authored
feat: add namespace to logging scope and make ResourceWatcher more extensible (#889)
1 parent f7b1b80 commit 0e65443

File tree

2 files changed

+61
-60
lines changed

2 files changed

+61
-60
lines changed

src/KubeOps.Operator/Queue/TimedEntityQueue.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace KubeOps.Operator.Queue;
1010
/// The given enumerable only contains items that should be considered for reconciliations.
1111
/// </summary>
1212
/// <typeparam name="TEntity">The type of the inner entity.</typeparam>
13-
internal sealed class TimedEntityQueue<TEntity> : IDisposable
13+
public sealed class TimedEntityQueue<TEntity> : IDisposable
1414
where TEntity : IKubernetesObject<V1ObjectMeta>
1515
{
1616
// A shared task factory for all the created tasks.

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

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
namespace KubeOps.Operator.Watcher;
2121

22-
internal class ResourceWatcher<TEntity>(
22+
public class ResourceWatcher<TEntity>(
2323
ILogger<ResourceWatcher<TEntity>> logger,
2424
IServiceProvider provider,
2525
TimedEntityQueue<TEntity> requeue,
@@ -127,6 +127,64 @@ static async ValueTask CastAndDispose(IDisposable resource)
127127
}
128128
}
129129

130+
protected virtual async Task OnEventAsync(WatchEventType type, TEntity entity, CancellationToken cancellationToken)
131+
{
132+
switch (type)
133+
{
134+
case WatchEventType.Added:
135+
if (_entityCache.TryAdd(entity.Uid(), entity.Generation() ?? 0))
136+
{
137+
// Only perform reconciliation if the entity was not already in the cache.
138+
await ReconcileModificationAsync(entity, cancellationToken);
139+
}
140+
else
141+
{
142+
logger.LogDebug(
143+
"""Received ADDED event for entity "{Kind}/{Name}" which was already in the cache. Skip event.""",
144+
entity.Kind,
145+
entity.Name());
146+
}
147+
148+
break;
149+
case WatchEventType.Modified:
150+
switch (entity)
151+
{
152+
case { Metadata.DeletionTimestamp: null }:
153+
_entityCache.TryGetValue(entity.Uid(), out var cachedGeneration);
154+
155+
// Check if entity spec has changed through "Generation" value increment. Skip reconcile if not changed.
156+
if (entity.Generation() <= cachedGeneration)
157+
{
158+
logger.LogDebug(
159+
"""Entity "{Kind}/{Name}" modification did not modify generation. Skip event.""",
160+
entity.Kind,
161+
entity.Name());
162+
return;
163+
}
164+
165+
// update cached generation since generation now changed
166+
_entityCache.TryUpdate(entity.Uid(), entity.Generation() ?? 1, cachedGeneration);
167+
await ReconcileModificationAsync(entity, cancellationToken);
168+
break;
169+
case { Metadata: { DeletionTimestamp: not null, Finalizers.Count: > 0 } }:
170+
await ReconcileFinalizersSequentialAsync(entity, cancellationToken);
171+
break;
172+
}
173+
174+
break;
175+
case WatchEventType.Deleted:
176+
await ReconcileDeletionAsync(entity, cancellationToken);
177+
break;
178+
default:
179+
logger.LogWarning(
180+
"""Received unsupported event "{EventType}" for "{Kind}/{Name}".""",
181+
type,
182+
entity.Kind,
183+
entity.Name());
184+
break;
185+
}
186+
}
187+
130188
private async Task WatchClientEventsAsync(CancellationToken stoppingToken)
131189
{
132190
string? currentVersion = null;
@@ -149,6 +207,7 @@ private async Task WatchClientEventsAsync(CancellationToken stoppingToken)
149207

150208
// ReSharper disable once RedundantAnonymousTypePropertyName
151209
Kind = entity.Kind,
210+
Namespace = entity.Namespace(),
152211
Name = entity.Name(),
153212
ResourceVersion = entity.ResourceVersion(),
154213
});
@@ -221,64 +280,6 @@ void LogReconciliationFailed(Exception exception)
221280
}
222281
}
223282

224-
private async Task OnEventAsync(WatchEventType type, TEntity entity, CancellationToken cancellationToken)
225-
{
226-
switch (type)
227-
{
228-
case WatchEventType.Added:
229-
if (_entityCache.TryAdd(entity.Uid(), entity.Generation() ?? 0))
230-
{
231-
// Only perform reconciliation if the entity was not already in the cache.
232-
await ReconcileModificationAsync(entity, cancellationToken);
233-
}
234-
else
235-
{
236-
logger.LogDebug(
237-
"""Received ADDED event for entity "{Kind}/{Name}" which was already in the cache. Skip event.""",
238-
entity.Kind,
239-
entity.Name());
240-
}
241-
242-
break;
243-
case WatchEventType.Modified:
244-
switch (entity)
245-
{
246-
case { Metadata.DeletionTimestamp: null }:
247-
_entityCache.TryGetValue(entity.Uid(), out var cachedGeneration);
248-
249-
// Check if entity spec has changed through "Generation" value increment. Skip reconcile if not changed.
250-
if (entity.Generation() <= cachedGeneration)
251-
{
252-
logger.LogDebug(
253-
"""Entity "{Kind}/{Name}" modification did not modify generation. Skip event.""",
254-
entity.Kind,
255-
entity.Name());
256-
return;
257-
}
258-
259-
// update cached generation since generation now changed
260-
_entityCache.TryUpdate(entity.Uid(), entity.Generation() ?? 1, cachedGeneration);
261-
await ReconcileModificationAsync(entity, cancellationToken);
262-
break;
263-
case { Metadata: { DeletionTimestamp: not null, Finalizers.Count: > 0 } }:
264-
await ReconcileFinalizersSequentialAsync(entity, cancellationToken);
265-
break;
266-
}
267-
268-
break;
269-
case WatchEventType.Deleted:
270-
await ReconcileDeletionAsync(entity!, cancellationToken);
271-
break;
272-
default:
273-
logger.LogWarning(
274-
"""Received unsupported event "{EventType}" for "{Kind}/{Name}".""",
275-
type,
276-
entity.Kind,
277-
entity.Name());
278-
break;
279-
}
280-
}
281-
282283
private async Task OnWatchErrorAsync(Exception e)
283284
{
284285
switch (e)

0 commit comments

Comments
 (0)