Skip to content

Commit ecaab5c

Browse files
authored
Support for schedules (#175)
1 parent 67741fc commit ecaab5c

25 files changed

+2579
-60
lines changed

temporalio/.rubocop.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ AllCops:
2121
Layout/ClassStructure:
2222
Enabled: true
2323

24+
# RBS annotations allowed
25+
Layout/LeadingCommentSpace:
26+
AllowRBSInlineAnnotation: true
27+
2428
# Don't need super for activities
2529
Lint/MissingSuper:
2630
AllowedParentClasses:

temporalio/lib/temporalio/client.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
require 'temporalio/client/async_activity_handle'
77
require 'temporalio/client/connection'
88
require 'temporalio/client/interceptor'
9+
require 'temporalio/client/schedule'
10+
require 'temporalio/client/schedule_handle'
911
require 'temporalio/client/workflow_execution'
1012
require 'temporalio/client/workflow_execution_count'
1113
require 'temporalio/client/workflow_handle'
@@ -358,6 +360,67 @@ def count_workflows(query = nil, rpc_options: nil)
358360
@impl.count_workflows(Interceptor::CountWorkflowsInput.new(query:, rpc_options:))
359361
end
360362

363+
# Create a schedule and return its handle.
364+
#
365+
# @param id [String] Unique identifier of the schedule.
366+
# @param schedule [Schedule] Schedule to create.
367+
# @param trigger_immediately [Boolean] If true, trigger one action immediately when creating the schedule.
368+
# @param backfills [Array<Schedule::Backfill>] Set of time periods to take actions on as if that time passed right
369+
# now.
370+
# @param memo [Hash<String, Object>, nil] Memo for the schedule. Memo for a scheduled workflow is part of the
371+
# schedule action.
372+
# @param search_attributes [SearchAttributes, nil] Search attributes for the schedule. Search attributes for a
373+
# scheduled workflow are part of the scheduled action.
374+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
375+
#
376+
# @return [ScheduleHandle] A handle to the created schedule.
377+
# @raise [Error::ScheduleAlreadyRunningError] If a schedule with this ID is already running.
378+
# @raise [Error::RPCError] RPC error from call.
379+
def create_schedule(
380+
id,
381+
schedule,
382+
trigger_immediately: false,
383+
backfills: [],
384+
memo: nil,
385+
search_attributes: nil,
386+
rpc_options: nil
387+
)
388+
@impl.create_schedule(Interceptor::CreateScheduleInput.new(
389+
id:,
390+
schedule:,
391+
trigger_immediately:,
392+
backfills:,
393+
memo:,
394+
search_attributes:,
395+
rpc_options:
396+
))
397+
end
398+
399+
# Get a schedule handle to an existing schedule for the given ID.
400+
#
401+
# @param id [String] Schedule ID to get a handle to.
402+
# @return [ScheduleHandle] The schedule handle.
403+
def schedule_handle(id)
404+
ScheduleHandle.new(client: self, id:)
405+
end
406+
407+
# List schedules.
408+
#
409+
# Note, this list is eventually consistent. Therefore if a schedule is added or deleted, it may not be available in
410+
# the list immediately.
411+
#
412+
# @param query [String] A Temporal visibility list filter.
413+
# @param rpc_options [RPCOptions, nil] Advanced RPC options.
414+
#
415+
# @return [Enumerator<Schedule::List::Description>] Enumerable schedules.
416+
#
417+
# @raise [Error::RPCError] RPC error from call.
418+
#
419+
# @see https://docs.temporal.io/visibility
420+
def list_schedules(query = nil, rpc_options: nil)
421+
@impl.list_schedules(Interceptor::ListSchedulesInput.new(query:, rpc_options:))
422+
end
423+
361424
# Get an async activity handle.
362425
#
363426
# @param task_token_or_id_reference [String, ActivityIDReference] Task token string or activity ID reference.

temporalio/lib/temporalio/client/interceptor.rb

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,79 @@ def intercept_client(next_interceptor)
137137
keyword_init: true
138138
)
139139

140+
# Input for {Outbound.create_schedule}.
141+
CreateScheduleInput = Struct.new(
142+
:id,
143+
:schedule,
144+
:trigger_immediately,
145+
:backfills,
146+
:memo,
147+
:search_attributes,
148+
:rpc_options,
149+
keyword_init: true
150+
)
151+
152+
# Input for {Outbound.list_schedules}.
153+
ListSchedulesInput = Struct.new(
154+
:query,
155+
:rpc_options,
156+
keyword_init: true
157+
)
158+
159+
# Input for {Outbound.backfill_schedule}.
160+
BackfillScheduleInput = Struct.new(
161+
:id,
162+
:backfills,
163+
:rpc_options,
164+
keyword_init: true
165+
)
166+
167+
# Input for {Outbound.delete_schedule}.
168+
DeleteScheduleInput = Struct.new(
169+
:id,
170+
:rpc_options,
171+
keyword_init: true
172+
)
173+
174+
# Input for {Outbound.describe_schedule}.
175+
DescribeScheduleInput = Struct.new(
176+
:id,
177+
:rpc_options,
178+
keyword_init: true
179+
)
180+
181+
# Input for {Outbound.pause_schedule}.
182+
PauseScheduleInput = Struct.new(
183+
:id,
184+
:note,
185+
:rpc_options,
186+
keyword_init: true
187+
)
188+
189+
# Input for {Outbound.trigger_schedule}.
190+
TriggerScheduleInput = Struct.new(
191+
:id,
192+
:overlap,
193+
:rpc_options,
194+
keyword_init: true
195+
)
196+
197+
# Input for {Outbound.unpause_schedule}.
198+
UnpauseScheduleInput = Struct.new(
199+
:id,
200+
:note,
201+
:rpc_options,
202+
keyword_init: true
203+
)
204+
205+
# Input for {Outbound.update_schedule}.
206+
UpdateScheduleInput = Struct.new(
207+
:id,
208+
:updater,
209+
:rpc_options,
210+
keyword_init: true
211+
)
212+
140213
# Input for {Outbound.heartbeat_async_activity}.
141214
HeartbeatAsyncActivityInput = Struct.new(
142215
:task_token_or_id_reference,
@@ -268,6 +341,72 @@ def terminate_workflow(input)
268341
next_interceptor.terminate_workflow(input)
269342
end
270343

344+
# Called for every {Client.create_schedule} call.
345+
#
346+
# @param input [CreateScheduleInput] Input.
347+
# @return [ScheduleHandle] Schedule handle.
348+
def create_schedule(input)
349+
next_interceptor.create_schedule(input)
350+
end
351+
352+
# Called for every {Client.list_schedules} call.
353+
#
354+
# @param input [ListSchedulesInput] Input.
355+
# @return [Enumerator<Schedule::List::Description>] Enumerable schedules.
356+
def list_schedules(input)
357+
next_interceptor.list_schedules(input)
358+
end
359+
360+
# Called for every {ScheduleHandle.backfill} call.
361+
#
362+
# @param input [BackfillScheduleInput] Input.
363+
def backfill_schedule(input)
364+
next_interceptor.backfill_schedule(input)
365+
end
366+
367+
# Called for every {ScheduleHandle.delete} call.
368+
#
369+
# @param input [DeleteScheduleInput] Input.
370+
def delete_schedule(input)
371+
next_interceptor.delete_schedule(input)
372+
end
373+
374+
# Called for every {ScheduleHandle.describe} call.
375+
#
376+
# @param input [DescribeScheduleInput] Input.
377+
# @return [Schedule::Description] Schedule description.
378+
def describe_schedule(input)
379+
next_interceptor.describe_schedule(input)
380+
end
381+
382+
# Called for every {ScheduleHandle.pause} call.
383+
#
384+
# @param input [PauseScheduleInput] Input.
385+
def pause_schedule(input)
386+
next_interceptor.pause_schedule(input)
387+
end
388+
389+
# Called for every {ScheduleHandle.trigger} call.
390+
#
391+
# @param input [TriggerScheduleInput] Input.
392+
def trigger_schedule(input)
393+
next_interceptor.trigger_schedule(input)
394+
end
395+
396+
# Called for every {ScheduleHandle.unpause} call.
397+
#
398+
# @param input [UnpauseScheduleInput] Input.
399+
def unpause_schedule(input)
400+
next_interceptor.unpause_schedule(input)
401+
end
402+
403+
# Called for every {ScheduleHandle.update} call.
404+
#
405+
# @param input [UpdateScheduleInput] Input.
406+
def update_schedule(input)
407+
next_interceptor.update_schedule(input)
408+
end
409+
271410
# Called for every {AsyncActivityHandle.heartbeat} call.
272411
#
273412
# @param input [HeartbeatAsyncActivityInput] Input.

0 commit comments

Comments
 (0)