2020// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121// THE SOFTWARE.
2222
23+ // (-- api-linter: core::0203::optional=disabled
24+ // aip.dev/not-precedent: field_behavior annotation not available in our gogo fork --)
25+ // (-- api-linter: core::0203::input-only=disabled
26+ // aip.dev/not-precedent: field_behavior annotation not available in our gogo fork --)
27+
2328syntax = "proto3" ;
2429
2530package temporal.api.schedule.v1 ;
@@ -41,21 +46,23 @@ import "temporal/api/enums/v1/schedule.proto";
4146import "temporal/api/workflow/v1/message.proto" ;
4247
4348// CalendarSpec describes an event specification relative to the calendar,
44- // similar to a traditional cron specification. Each field can be one of:
49+ // similar to a traditional cron specification, but with labeled fields. Each
50+ // field can be one of:
4551// *: matches always
4652// x: matches when the field equals x
4753// x/y : matches when the field equals x+n*y where n is an integer
4854// x-z: matches when the field is between x and z inclusive
4955// w,x,y,...: matches when the field is one of the listed values
5056// Each x, y, z, ... is either a decimal integer, or a month or day of week name
5157// or abbreviation (in the appropriate fields).
52- // A second in time matches if all fields match.
58+ // A timestamp matches if all fields match.
59+ // Note that fields have different default values, for convenience.
5360// Note that the special case that some cron implementations have for treating
5461// day_of_month and day_of_week as "or" instead of "and" when both are set is
5562// not implemented.
5663// day_of_week can accept 0 or 7 as Sunday
57- // TODO: add relative-to-end-of-month
58- // TODO: add nth day-of-week in month
64+ // CalendarSpec gets compiled into StructuredCalendarSpec, which is what will be
65+ // returned if you describe the schedule.
5966message CalendarSpec {
6067 // Expression to match seconds. Default: 0
6168 string second = 1 ;
@@ -73,6 +80,51 @@ message CalendarSpec {
7380 string year = 6 ;
7481 // Expression to match days of the week. Default: *
7582 string day_of_week = 7 ;
83+ // Free-form comment describing the intention of this spec.
84+ string comment = 8 ;
85+ }
86+
87+ // Range represents a set of integer values, used to match fields of a calendar
88+ // time in StructuredCalendarSpec. If end < start, then end is interpreted as
89+ // equal to start. This means you can use a Range with start set to a value, and
90+ // end and step unset (defaulting to 0) to represent a single value.
91+ message Range {
92+ // Start of range (inclusive).
93+ int32 start = 1 ;
94+ // End of range (inclusive).
95+ int32 end = 2 ;
96+ // Step (optional, default 1).
97+ int32 step = 3 ;
98+ }
99+
100+ // StructuredCalendarSpec describes an event specification relative to the
101+ // calendar, in a form that's easy to work with programmatically. Each field can
102+ // be one or more ranges.
103+ // A timestamp matches if at least one range of each field matches the
104+ // corresponding fields of the timestamp, except for year: if year is missing,
105+ // that means all years match. For all fields besides year, at least one Range
106+ // must be present to match anything.
107+ // TODO: add relative-to-end-of-month
108+ // TODO: add nth day-of-week in month
109+ message StructuredCalendarSpec {
110+ // Match seconds (0-59)
111+ repeated Range second = 1 ;
112+ // Match minutes (0-59)
113+ repeated Range minute = 2 ;
114+ // Match hours (0-23)
115+ repeated Range hour = 3 ;
116+ // Match days of the month (1-31)
117+ // (-- api-linter: core::0140::prepositions=disabled
118+ // aip.dev/not-precedent: standard name of field --)
119+ repeated Range day_of_month = 4 ;
120+ // Match months (1-12)
121+ repeated Range month = 5 ;
122+ // Match years.
123+ repeated Range year = 6 ;
124+ // Match days of the week (0-6; 0 is Sunday).
125+ repeated Range day_of_week = 7 ;
126+ // Free-form comment describing the intention of this spec.
127+ string comment = 8 ;
76128}
77129
78130// IntervalSpec matches times that can be expressed as:
@@ -97,24 +149,56 @@ message IntervalSpec {
97149// definition of a time zone can change over time (most commonly, when daylight
98150// saving time policy changes for an area). To create a totally self-contained
99151// ScheduleSpec, use UTC or include timezone_data.
152+ //
153+ // For input, you can provide zero or more of: structured_calendar, calendar,
154+ // cron_string, interval, and exclude_structured_calendar, and all of them will
155+ // be used (the schedule will take action at the union of all of their times,
156+ // minus the ones that match exclude_structured_calendar).
157+ //
158+ // On input, calendar and cron_string fields will be compiled into
159+ // structured_calendar (and maybe interval and timezone_name), so if you
160+ // Describe a schedule, you'll see only structured_calendar, interval, etc.
100161message ScheduleSpec {
162+ // Calendar-based specifications of times.
163+ repeated StructuredCalendarSpec structured_calendar = 7 ;
164+ // cron_string holds a traditional cron specification as a string. It
165+ // accepts 5, 6, or 7 fields, separated by spaces, and interprets them the
166+ // same way as CalendarSpec.
167+ // 5 fields: minute, hour, day_of_month, month, day_of_week
168+ // 6 fields: minute, hour, day_of_month, month, day_of_week, year
169+ // 7 fields: second, minute, hour, day_of_month, month, day_of_week, year
170+ // If year is not given, it defaults to *. If second is not given, it
171+ // defaults to 0.
172+ // Shorthands @yearly, @monthly, @weekly, @daily, and @hourly are also
173+ // accepted instead of the 5-7 time fields.
174+ // Optionally, the string can be preceded by CRON_TZ=<timezone name> or
175+ // TZ=<timezone name>, which will get copied to timezone_name. (There must
176+ // not also be a timezone_name present.)
177+ // Optionally "#" followed by a comment can appear at the end of the string.
178+ // Note that the special case that some cron implementations have for
179+ // treating day_of_month and day_of_week as "or" instead of "and" when both
180+ // are set is not implemented.
181+ // @every <interval>[/<phase>] is accepted and gets compiled into an
182+ // IntervalSpec instead. <interval> and <phase> should be a decimal integer
183+ // with a unit suffix s, m, h, or d.
184+ repeated string cron_string = 8 ;
101185 // Calendar-based specifications of times.
102186 repeated CalendarSpec calendar = 1 ;
103187 // Interval-based specifications of times.
104188 repeated IntervalSpec interval = 2 ;
105- // Any timestamps matching any of the exclude_calendar specs will be
106- // skipped.
107- repeated CalendarSpec exclude_calendar = 3 ;
108- // Any timestamps before start_time will be skipped. Together, start_time
109- // and end_time make an inclusive interval.
189+ // Any timestamps matching any of exclude_* will be skipped.
190+ repeated CalendarSpec exclude_calendar = 3 [ deprecated = true ]; // use exclude_structured_calendar
191+ repeated StructuredCalendarSpec exclude_structured_calendar = 9 ;
192+ // If start_time is set, any timestamps before start_time will be skipped.
193+ // (Together, start_time and end_time make an inclusive interval.)
110194 google.protobuf.Timestamp start_time = 4 [(gogoproto.stdtime ) = true ];
111- // Any timestamps after end_time will be skipped.
195+ // If end_time is set, any timestamps after end_time will be skipped.
112196 google.protobuf.Timestamp end_time = 5 [(gogoproto.stdtime ) = true ];
113197 // All timestamps will be incremented by a random value from 0 to this
114- // amount of jitter. Default: 1 second
198+ // amount of jitter. Default: 0
115199 google.protobuf.Duration jitter = 6 [(gogoproto.stdduration ) = true ];
116200
117- // Time zone to interpret all CalendarSpecs in.
201+ // Time zone to interpret all calendar-based specs in.
118202 //
119203 // If unset, defaults to UTC. We recommend using UTC for your application if
120204 // at all possible, to avoid various surprising properties of time zones.
@@ -134,21 +218,17 @@ message ScheduleSpec {
134218 // at 2:30am and specify a time zone that follows DST, that action will not
135219 // be triggered on the day that has no 2:30am. Similarly, an action that
136220 // fires at 1:30am will be triggered twice on the day that has two 1:30s.
221+ //
222+ // Also note that no actions are taken on leap-seconds (e.g. 23:59:60 UTC).
137223 string timezone_name = 10 ;
138224 bytes timezone_data = 11 ;
139225}
140226
141227message SchedulePolicies {
142228 // Policy for overlaps.
143- // Note that this can be changed after a schedule has taken some actions, and we can't
144- // provide 100% sensible semantics for all changes. The most confusing case would be
145- // changes to/from ALLOW_ALL: with that policy multiple scheduled workflows can run
146- // concurrently, but for all other policies only one can run at a time. Changing
147- // between these two classes will leave all workflows with the other class alone.
148- // E.g., if changing from ALLOW_ALL to CANCEL_OTHER, and there are workflows running,
149- // those workflows will not be cancelled. If changing from ALLOW_ALL to SKIP with
150- // workflows running, the running workflows will not cause the next action to be
151- // skipped.
229+ // Note that this can be changed after a schedule has taken some actions,
230+ // and some changes might produce unintuitive results. In general, the later
231+ // policy overrides the earlier policy.
152232 temporal.api.enums.v1.ScheduleOverlapPolicy overlap_policy = 1 ;
153233
154234 // Policy for catchups:
@@ -195,10 +275,11 @@ message ScheduleState {
195275 // If true, do not take any actions based on the schedule spec.
196276 bool paused = 2 ;
197277
198- // If limited_actions is true, decrement remaining_actions after each action, and do
199- // not take any more scheduled actions if remaining_actions is zero. Actions may still
200- // be taken by explicit request. Skipped actions (due to overlap policy) do not count
201- // against remaining actions.
278+ // If limited_actions is true, decrement remaining_actions after each
279+ // action, and do not take any more scheduled actions if remaining_actions
280+ // is zero. Actions may still be taken by explicit request (i.e. trigger
281+ // immediately or backfill). Skipped actions (due to overlap policy) do not
282+ // count against remaining actions.
202283 bool limited_actions = 3 ;
203284 int64 remaining_actions = 4 ;
204285}
@@ -258,8 +339,7 @@ message ScheduleInfo {
258339 google.protobuf.Timestamp create_time = 6 [(gogoproto.stdtime ) = true ];
259340 google.protobuf.Timestamp update_time = 7 [(gogoproto.stdtime ) = true ];
260341
261- // Error for invalid schedule. If this is set, no actions will be taken.
262- string invalid_schedule_error = 8 ;
342+ string invalid_schedule_error = 8 [deprecated = true ];
263343}
264344
265345message Schedule {
@@ -273,8 +353,7 @@ message Schedule {
273353// that's returned in ListSchedules.
274354message ScheduleListInfo {
275355 // From spec:
276- // Some fields are too large/unimportant for the purpose of listing, so we'll clear them
277- // from this copy of spec: exclude_calendar, jitter, timezone_data.
356+ // Some fields are dropped from this copy of spec: timezone_data
278357 ScheduleSpec spec = 1 ;
279358
280359 // From action:
0 commit comments