Skip to content

Commit faa6422

Browse files
feat(Schedule): support query for listing schedules (#1535)
1 parent 07084fc commit faa6422

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

packages/client/src/schedule-client.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ export interface ListScheduleOptions {
162162
* @default 1000
163163
*/
164164
pageSize?: number;
165+
/**
166+
* Filter schedules by a query string.
167+
*/
168+
query?: string;
165169
}
166170

167171
/**
@@ -368,6 +372,7 @@ export class ScheduleClient extends BaseClient {
368372
nextPageToken,
369373
namespace: this.options.namespace,
370374
maximumPageSize: options?.pageSize,
375+
query: options?.query,
371376
});
372377
} catch (e) {
373378
this.rethrowGrpcError(e, 'Failed to list schedules', undefined);

packages/test/src/test-schedules.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ScheduleHandle,
1111
ScheduleSummary,
1212
ScheduleUpdateOptions,
13+
SearchAttributes,
1314
} from '@temporalio/client';
1415
import { msToNumber } from '@temporalio/common/lib/time';
1516
import { registerDefaultCustomSearchAttributes, RUN_INTEGRATION_TESTS } from './helpers';
@@ -542,6 +543,70 @@ if (RUN_INTEGRATION_TESTS) {
542543
}
543544
});
544545

546+
test.serial('Can list Schedules with a query string', async (t) => {
547+
const { client } = t.context;
548+
549+
const groupId = randomUUID();
550+
const createdScheduleHandlesPromises = [];
551+
const expectedIds: string[] = [];
552+
for (let i = 0; i < 4; i++) {
553+
const scheduleId = `test-query-${groupId}-${i + 1}`;
554+
const searchAttributes: SearchAttributes = {};
555+
if (i < 2) {
556+
searchAttributes['CustomKeywordField'] = ['some-value'];
557+
expectedIds.push(scheduleId);
558+
}
559+
createdScheduleHandlesPromises.push(
560+
client.schedule.create({
561+
scheduleId,
562+
spec: {
563+
calendars: [{ hour: { start: 2, end: 7, step: 1 } }],
564+
},
565+
action: {
566+
type: 'startWorkflow',
567+
workflowType: dummyWorkflow,
568+
taskQueue,
569+
},
570+
searchAttributes,
571+
})
572+
);
573+
}
574+
575+
const createdScheduleHandles: { [k: string]: ScheduleHandle } = Object.fromEntries(
576+
(await Promise.all(createdScheduleHandlesPromises)).map((x) => [x.scheduleId, x])
577+
);
578+
579+
try {
580+
// Wait for visibility to stabilize
581+
await asyncRetry(
582+
async () => {
583+
const listedScheduleHandlesFromQuery: ScheduleSummary[] = []; // to list all the schedule handles from the query string provided
584+
const query = `CustomKeywordField="some-value"`;
585+
586+
for await (const schedule of client.schedule.list({ query })) {
587+
listedScheduleHandlesFromQuery.push(schedule);
588+
}
589+
590+
const listedScheduleIdsFromQuery = listedScheduleHandlesFromQuery.map((x) => x.scheduleId).sort();
591+
592+
if (listedScheduleIdsFromQuery.length !== expectedIds.length) throw new Error('Entries are missing');
593+
594+
t.deepEqual(listedScheduleIdsFromQuery, expectedIds);
595+
},
596+
{
597+
retries: 60,
598+
maxTimeout: 1000,
599+
}
600+
);
601+
602+
t.pass();
603+
} finally {
604+
for (const handle of Object.values(createdScheduleHandles)) {
605+
await handle.delete();
606+
}
607+
}
608+
});
609+
545610
test.serial('Structured calendar specs are encoded and decoded properly', async (t) => {
546611
const checks: { input: CalendarSpec; expected: CalendarSpecDescription; comment?: string }[] = [
547612
{

0 commit comments

Comments
 (0)