Skip to content

Commit de986bf

Browse files
fix: Use namespace and name for requeueing of entities (#801)
Fixes #800
1 parent d408fe0 commit de986bf

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

src/KubeOps.Operator/Queue/TimedEntityQueue.cs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ internal sealed class TimedEntityQueue<TEntity> : IDisposable
3333
public void Enqueue(TEntity entity, TimeSpan requeueIn)
3434
{
3535
_management.AddOrUpdate(
36-
entity.Name() ?? throw new InvalidOperationException("Cannot enqueue entities without name."),
36+
GetKey(entity) ?? throw new InvalidOperationException("Cannot enqueue entities without name."),
3737
key =>
3838
{
3939
var entry = new TimedQueueEntry<TEntity>(entity, requeueIn);
@@ -81,15 +81,30 @@ public async IAsyncEnumerator<TEntity> GetAsyncEnumerator(CancellationToken canc
8181

8282
public void Remove(TEntity entity)
8383
{
84-
var name = entity.Name();
85-
if (name is null)
84+
var key = GetKey(entity);
85+
if (key is null)
8686
{
8787
return;
8888
}
8989

90-
if (_management.Remove(name, out var task))
90+
if (_management.Remove(key, out var task))
9191
{
9292
task.Cancel();
9393
}
9494
}
95+
96+
private string? GetKey(TEntity entity)
97+
{
98+
if (entity.Name() is null)
99+
{
100+
return null;
101+
}
102+
103+
if (entity.Namespace() is null)
104+
{
105+
return entity.Name();
106+
}
107+
108+
return $"{entity.Namespace()}/{entity.Name()}";
109+
}
95110
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using k8s.Models;
2+
3+
using KubeOps.Operator.Queue;
4+
5+
namespace KubeOps.Operator.Test.Queue;
6+
7+
public class TimedEntityQueueTest
8+
{
9+
[Fact]
10+
public async Task Can_Enqueue_Multiple_Entities_With_Same_Name()
11+
{
12+
var queue = new TimedEntityQueue<V1Secret>();
13+
14+
queue.Enqueue(CreateSecret("app-ns1", "secret-name"), TimeSpan.FromSeconds(1));
15+
queue.Enqueue(CreateSecret("app-ns2", "secret-name"), TimeSpan.FromSeconds(1));
16+
17+
var items = new List<V1Secret>();
18+
19+
var tokenSource = new CancellationTokenSource();
20+
tokenSource.CancelAfter(TimeSpan.FromSeconds(2));
21+
22+
var enumerator = queue.GetAsyncEnumerator(tokenSource.Token);
23+
24+
try
25+
{
26+
while (await enumerator.MoveNextAsync())
27+
{
28+
items.Add(enumerator.Current);
29+
}
30+
}
31+
catch (OperationCanceledException)
32+
{
33+
// We expect to timeout watching the queue so that we can assert the items received
34+
}
35+
36+
Assert.Equal(2, items.Count);
37+
}
38+
39+
private V1Secret CreateSecret(string secretNamespace, string secretName)
40+
{
41+
var secret = new V1Secret();
42+
secret.EnsureMetadata();
43+
44+
secret.Metadata.SetNamespace(secretNamespace);
45+
secret.Metadata.Name = secretName;
46+
47+
return secret;
48+
}
49+
}

0 commit comments

Comments
 (0)