@@ -66,7 +66,8 @@ func TestRegistryImpl_RecordWorkerHeartbeat(t *testing.T) {
6666 for _ , tt := range tests {
6767 t .Run (tt .name , func (t * testing.T ) {
6868 r := newRegistryImpl (
69- defaultBuckets , defaultEntryTTL , defaultMinEvictAge , defaultMaxEntries , defaultEvictionInterval ,
69+ defaultBuckets , defaultEntryTTL , defaultMinEvictAge , defaultMaxEntries ,
70+ defaultEvictionInterval ,
7071 )
7172 tt .setup (r )
7273
@@ -164,7 +165,8 @@ func TestRegistryImpl_ListWorkers(t *testing.T) {
164165 for _ , tt := range tests {
165166 t .Run (tt .name , func (t * testing.T ) {
166167 r := newRegistryImpl (
167- defaultBuckets , defaultEntryTTL , defaultMinEvictAge , defaultMaxEntries , defaultEvictionInterval ,
168+ defaultBuckets , defaultEntryTTL , defaultMinEvictAge , defaultMaxEntries ,
169+ defaultEvictionInterval ,
168170 )
169171 tt .setup (r )
170172
@@ -195,6 +197,127 @@ func TestRegistryImpl_ListWorkers(t *testing.T) {
195197 }
196198}
197199
200+ // Exercises the query matching functionality of ListWorkers.
201+ func TestRegistryImpl_ListWorkersWithQuery (t * testing.T ) {
202+ tests := []struct {
203+ name string
204+ setup func (* registryImpl )
205+ nsID namespace.ID
206+ query string
207+ expectedCount int
208+ expectedWorkers []string // WorkerInstanceKeys
209+ expectedError string // Expected error message (empty if no error expected)
210+ }{
211+ {
212+ name : "valid query - basic filtering" ,
213+ setup : func (r * registryImpl ) {
214+ r .upsertHeartbeats ("namespace1" , []* workerpb.WorkerHeartbeat {
215+ {WorkerInstanceKey : "worker1" , TaskQueue : "queue1" },
216+ {WorkerInstanceKey : "worker2" , TaskQueue : "queue2" },
217+ })
218+ },
219+ nsID : "namespace1" ,
220+ query : "WorkerInstanceKey = 'worker1'" ,
221+ expectedCount : 1 ,
222+ expectedWorkers : []string {"worker1" },
223+ },
224+ {
225+ name : "valid compound query - multiple conditions" ,
226+ setup : func (r * registryImpl ) {
227+ r .upsertHeartbeats ("namespace1" , []* workerpb.WorkerHeartbeat {
228+ {WorkerInstanceKey : "worker1" , TaskQueue : "queue1" },
229+ {WorkerInstanceKey : "worker2" , TaskQueue : "queue2" },
230+ })
231+ },
232+ nsID : "namespace1" ,
233+ query : "WorkerInstanceKey = 'worker1' AND TaskQueue = 'queue1'" ,
234+ expectedCount : 1 ,
235+ expectedWorkers : []string {"worker1" },
236+ },
237+ {
238+ name : "valid query - no matches" ,
239+ setup : func (r * registryImpl ) {
240+ r .upsertHeartbeats ("namespace1" , []* workerpb.WorkerHeartbeat {
241+ {WorkerInstanceKey : "worker1" , TaskQueue : "queue1" },
242+ })
243+ },
244+ nsID : "namespace1" ,
245+ query : "TaskQueue = 'non-existent-queue'" ,
246+ expectedCount : 0 ,
247+ expectedWorkers : []string {},
248+ },
249+ {
250+ name : "invalid query - malformed SQL" ,
251+ setup : func (r * registryImpl ) {
252+ r .upsertHeartbeats ("namespace1" , []* workerpb.WorkerHeartbeat {
253+ {WorkerInstanceKey : "worker1" },
254+ })
255+ },
256+ nsID : "namespace1" ,
257+ query : "invalid SQL syntax here" ,
258+ expectedError : "malformed query" ,
259+ },
260+ {
261+ name : "query on empty namespace" ,
262+ setup : func (r * registryImpl ) {
263+ // No workers added
264+ },
265+ nsID : "empty-namespace" ,
266+ query : "WorkerInstanceKey = 'worker1'" ,
267+ expectedCount : 0 ,
268+ expectedWorkers : []string {},
269+ },
270+ {
271+ name : "query returns requested namespace only" ,
272+ setup : func (r * registryImpl ) {
273+ // Add workers to namespace1
274+ r .upsertHeartbeats ("namespace1" , []* workerpb.WorkerHeartbeat {
275+ {WorkerInstanceKey : "worker1" , TaskQueue : "queue" },
276+ })
277+ // Add workers to namespace2
278+ r .upsertHeartbeats ("namespace2" , []* workerpb.WorkerHeartbeat {
279+ {WorkerInstanceKey : "worker2" , TaskQueue : "queue" },
280+ })
281+ },
282+ nsID : "namespace1" ,
283+ query : "TaskQueue = 'queue'" ,
284+ expectedCount : 1 ,
285+ expectedWorkers : []string {"worker1" }, // Only worker1, not worker2 from namespace2
286+ },
287+ }
288+
289+ for _ , tt := range tests {
290+ t .Run (tt .name , func (t * testing.T ) {
291+ r := newRegistryImpl (
292+ defaultBuckets , defaultEntryTTL , defaultMinEvictAge , defaultMaxEntries ,
293+ defaultEvictionInterval ,
294+ )
295+ tt .setup (r )
296+
297+ result , err := r .ListWorkers (tt .nsID , tt .query , nil )
298+
299+ if tt .expectedError != "" {
300+ assert .Error (t , err , "expected an error for invalid query" )
301+ assert .Contains (t , err .Error (), tt .expectedError , "error message should contain expected text" )
302+ assert .Nil (t , result , "result should be nil when an error occurs" )
303+ return
304+ }
305+
306+ assert .NoError (t , err , "unexpected error when listing workers with query" )
307+ assert .Len (t , result , tt .expectedCount , "unexpected number of workers returned" )
308+
309+ // Check that all expected workers are present
310+ if tt .expectedCount > 0 {
311+ actualWorkers := make ([]string , len (result ))
312+ for i , worker := range result {
313+ actualWorkers [i ] = worker .WorkerInstanceKey
314+ }
315+ assert .ElementsMatch (t , tt .expectedWorkers , actualWorkers , "worker lists don't match" )
316+ }
317+ })
318+ }
319+ }
320+
198321func TestRegistryImpl_DescribeWorker (t * testing.T ) {
199322 tests := []struct {
200323 name string
@@ -270,7 +393,8 @@ func TestRegistryImpl_DescribeWorker(t *testing.T) {
270393 for _ , tt := range tests {
271394 t .Run (tt .name , func (t * testing.T ) {
272395 r := newRegistryImpl (
273- defaultBuckets , defaultEntryTTL , defaultMinEvictAge , defaultMaxEntries , defaultEvictionInterval ,
396+ defaultBuckets , defaultEntryTTL , defaultMinEvictAge , defaultMaxEntries ,
397+ defaultEvictionInterval ,
274398 )
275399 tt .setup (r )
276400
0 commit comments