0
# Timer Service
1
2
Scheduled task execution and automation with support for one-time and recurring schedules, complex timing patterns, and integration with other Globus services. The Timer service enables automated execution of operations like data transfers, compute jobs, and workflow triggers based on flexible scheduling requirements.
3
4
## Capabilities
5
6
### Timers Client
7
8
Core client for timer creation, management, and monitoring with support for various schedule types and integration with Transfer and other Globus services.
9
10
```python { .api }
11
class TimersClient(BaseClient):
12
"""
13
Client for Globus Timers service operations.
14
15
Provides methods for creating, managing, and monitoring scheduled tasks
16
with support for one-time and recurring schedules, transfer automation,
17
and integration with other Globus services.
18
"""
19
20
def __init__(
21
self,
22
*,
23
app: GlobusApp | None = None,
24
authorizer: GlobusAuthorizer | None = None,
25
environment: str | None = None,
26
base_url: str | None = None,
27
**kwargs
28
) -> None: ...
29
30
def add_app_transfer_data_access_scope(
31
self,
32
collection_ids: str | UUID | Iterable[str | UUID]
33
) -> TimersClient:
34
"""
35
Add dependent data_access scopes for transfer collections.
36
37
Adds required scopes to prevent ConsentRequired errors when creating
38
timers that use GCS mapped collections for automated transfers.
39
40
Parameters:
41
- collection_ids: Collection ID(s) requiring data access scopes
42
43
Returns:
44
Self for method chaining
45
"""
46
```
47
48
### Timer Creation and Management
49
50
Create, configure, and manage scheduled tasks with various schedule types and execution patterns.
51
52
```python { .api }
53
def create_timer(
54
self,
55
timer: dict[str, Any] | TransferTimer
56
) -> GlobusHTTPResponse:
57
"""
58
Create a new timer for scheduled execution.
59
60
Creates a timer with specified schedule and task definition.
61
Supports both one-time and recurring schedules with flexible
62
end conditions and execution parameters.
63
64
Parameters:
65
- timer: Timer specification including schedule and task details
66
67
Returns:
68
GlobusHTTPResponse with created timer details and UUID
69
"""
70
71
def get_timer(self, timer_id: str | UUID) -> GlobusHTTPResponse:
72
"""
73
Get detailed information about a specific timer.
74
75
Returns complete timer configuration including schedule,
76
execution history, and current status.
77
78
Parameters:
79
- timer_id: UUID of the timer to retrieve
80
81
Returns:
82
GlobusHTTPResponse with timer configuration and status
83
"""
84
85
def list_timers(
86
self,
87
*,
88
limit: int | None = None,
89
marker: str | None = None,
90
fields: str | None = None,
91
query_params: dict[str, Any] | None = None
92
) -> GlobusHTTPResponse:
93
"""
94
List timers with pagination and filtering support.
95
96
Returns timers accessible to the user with optional
97
field selection and pagination for large timer sets.
98
99
Parameters:
100
- limit: Maximum number of timers to return
101
- marker: Pagination marker for continuing listings
102
- fields: Comma-separated list of fields to include
103
- query_params: Additional query parameters
104
105
Returns:
106
GlobusHTTPResponse with paginated timer listings
107
"""
108
109
def update_timer(
110
self,
111
timer_id: str | UUID,
112
data: dict[str, Any],
113
*,
114
query_params: dict[str, Any] | None = None
115
) -> GlobusHTTPResponse:
116
"""
117
Update timer configuration.
118
119
Modifies timer settings including schedule, name, and other
120
configuration parameters. Some changes may affect future
121
executions only.
122
123
Parameters:
124
- timer_id: UUID of timer to update
125
- data: Updated timer configuration
126
- query_params: Additional parameters
127
128
Returns:
129
GlobusHTTPResponse confirming update
130
"""
131
132
def delete_timer(
133
self,
134
timer_id: str | UUID,
135
*,
136
query_params: dict[str, Any] | None = None
137
) -> GlobusHTTPResponse:
138
"""
139
Delete a timer.
140
141
Permanently removes a timer and stops any future scheduled
142
executions. Running executions may continue to completion.
143
144
Parameters:
145
- timer_id: UUID of timer to delete
146
- query_params: Additional parameters
147
148
Returns:
149
GlobusHTTPResponse confirming deletion
150
"""
151
152
def pause_timer(
153
self,
154
timer_id: str | UUID,
155
*,
156
query_params: dict[str, Any] | None = None
157
) -> GlobusHTTPResponse:
158
"""
159
Pause a timer temporarily.
160
161
Stops scheduled executions without deleting the timer.
162
Can be resumed later to continue the schedule.
163
164
Parameters:
165
- timer_id: UUID of timer to pause
166
- query_params: Additional parameters
167
168
Returns:
169
GlobusHTTPResponse confirming pause
170
"""
171
172
def resume_timer(
173
self,
174
timer_id: str | UUID,
175
*,
176
query_params: dict[str, Any] | None = None
177
) -> GlobusHTTPResponse:
178
"""
179
Resume a paused timer.
180
181
Restarts scheduled executions for a previously paused timer
182
according to its original schedule configuration.
183
184
Parameters:
185
- timer_id: UUID of timer to resume
186
- query_params: Additional parameters
187
188
Returns:
189
GlobusHTTPResponse confirming resume
190
"""
191
```
192
193
### Timer Data Classes and Schedules
194
195
Comprehensive data structures for defining timer schedules, execution patterns, and task specifications with type-safe construction.
196
197
```python { .api }
198
class TransferTimer(PayloadWrapper):
199
"""
200
Helper for creating transfer-specific timers.
201
202
Provides convenient interface for creating timers that execute
203
Globus Transfer operations on a schedule with proper scope
204
and permission handling.
205
"""
206
207
def __init__(
208
self,
209
*,
210
name: str,
211
schedule: OnceTimerSchedule | RecurringTimerSchedule | dict[str, Any],
212
body: TransferData | dict[str, Any],
213
**kwargs
214
) -> None: ...
215
216
class OnceTimerSchedule(PayloadWrapper):
217
"""
218
Schedule for timers that run exactly once.
219
220
Defines a single execution time for one-time scheduled tasks,
221
supporting both immediate execution and future scheduling.
222
"""
223
224
def __init__(
225
self,
226
datetime: str | dt.datetime | MissingType = MISSING,
227
**kwargs
228
) -> None: ...
229
230
class RecurringTimerSchedule(PayloadWrapper):
231
"""
232
Schedule for timers that run repeatedly.
233
234
Defines recurring execution with configurable intervals,
235
start times, and end conditions including date limits
236
and execution count limits.
237
"""
238
239
def __init__(
240
self,
241
interval_seconds: int,
242
*,
243
start: str | dt.datetime | MissingType = MISSING,
244
end: dict[str, Any] | MissingType = MISSING,
245
**kwargs
246
) -> None: ...
247
248
@classmethod
249
def every_hour(cls, **kwargs) -> RecurringTimerSchedule:
250
"""Create schedule that runs every hour."""
251
252
@classmethod
253
def every_day(cls, **kwargs) -> RecurringTimerSchedule:
254
"""Create schedule that runs daily."""
255
256
@classmethod
257
def every_week(cls, **kwargs) -> RecurringTimerSchedule:
258
"""Create schedule that runs weekly."""
259
260
@classmethod
261
def every_month(cls, **kwargs) -> RecurringTimerSchedule:
262
"""Create schedule that runs monthly (30 days)."""
263
264
class TimerJob(PayloadWrapper):
265
"""
266
Legacy timer job specification.
267
268
Note: This class is deprecated in favor of TransferTimer for
269
transfer operations. Still supported for non-transfer use cases.
270
"""
271
272
def __init__(
273
self,
274
*,
275
name: str,
276
callback_url: str,
277
start_time: str | dt.datetime | MissingType = MISSING,
278
interval: int | MissingType = MISSING,
279
stop_after: dict[str, Any] | MissingType = MISSING,
280
**kwargs
281
) -> None: ...
282
```
283
284
### Execution Monitoring and History
285
286
Monitor timer executions, view execution history, and track task results with comprehensive status information.
287
288
```python { .api }
289
def get_timer_executions(
290
self,
291
timer_id: str | UUID,
292
*,
293
limit: int | None = None,
294
marker: str | None = None,
295
query_params: dict[str, Any] | None = None
296
) -> GlobusHTTPResponse:
297
"""
298
Get execution history for a timer.
299
300
Returns list of past and scheduled executions with status
301
information, results, and timing details.
302
303
Parameters:
304
- timer_id: UUID of the timer
305
- limit: Maximum executions to return
306
- marker: Pagination marker
307
- query_params: Additional parameters
308
309
Returns:
310
GlobusHTTPResponse with execution history
311
"""
312
313
def get_execution(
314
self,
315
execution_id: str | UUID,
316
*,
317
query_params: dict[str, Any] | None = None
318
) -> GlobusHTTPResponse:
319
"""
320
Get detailed information about a specific execution.
321
322
Returns complete execution details including status,
323
results, error information, and timing data.
324
325
Parameters:
326
- execution_id: UUID of the execution
327
- query_params: Additional parameters
328
329
Returns:
330
GlobusHTTPResponse with execution details
331
"""
332
333
def cancel_execution(
334
self,
335
execution_id: str | UUID,
336
*,
337
query_params: dict[str, Any] | None = None
338
) -> GlobusHTTPResponse:
339
"""
340
Cancel a running or pending execution.
341
342
Attempts to stop an execution that is currently running
343
or scheduled to run soon.
344
345
Parameters:
346
- execution_id: UUID of execution to cancel
347
- query_params: Additional parameters
348
349
Returns:
350
GlobusHTTPResponse confirming cancellation request
351
"""
352
```
353
354
### Error Handling
355
356
Timer-specific error handling for scheduling and execution operations.
357
358
```python { .api }
359
class TimersAPIError(GlobusAPIError):
360
"""
361
Error class for Timers service API errors.
362
363
Provides enhanced error handling for timer-specific error
364
conditions including scheduling conflicts and execution failures.
365
"""
366
```
367
368
## Common Usage Patterns
369
370
### Basic Transfer Timer Creation
371
372
```python
373
from globus_sdk import TimersClient, TransferTimer, RecurringTimerSchedule, TransferData
374
375
# Initialize client with transfer data access scope
376
timers_client = TimersClient(app=app)
377
timers_client.add_app_transfer_data_access_scope([
378
"source-collection-uuid",
379
"dest-collection-uuid"
380
])
381
382
# Create transfer data specification
383
transfer_data = TransferData(
384
source_endpoint="source-collection-uuid",
385
destination_endpoint="dest-collection-uuid",
386
label="Automated Daily Backup"
387
)
388
transfer_data.add_item("/data/current/", "/backup/daily/", recursive=True)
389
390
# Create recurring schedule (daily at 2 AM)
391
daily_schedule = RecurringTimerSchedule(
392
interval_seconds=24 * 60 * 60, # 24 hours
393
start="2024-12-01T02:00:00Z" # Start at 2 AM UTC
394
)
395
396
# Create transfer timer
397
backup_timer = TransferTimer(
398
name="Daily Data Backup",
399
schedule=daily_schedule,
400
body=transfer_data
401
)
402
403
# Create the timer
404
timer_response = timers_client.create_timer(backup_timer)
405
timer_id = timer_response["timer"]["id"]
406
407
print(f"Created daily backup timer: {timer_id}")
408
```
409
410
### One-Time Scheduled Transfer
411
412
```python
413
from globus_sdk import OnceTimerSchedule
414
import datetime
415
416
# Schedule transfer for specific future time
417
future_time = datetime.datetime(2024, 12, 15, 14, 30, 0) # Dec 15, 2024 at 2:30 PM
418
once_schedule = OnceTimerSchedule(datetime=future_time)
419
420
# Create one-time transfer timer
421
maintenance_transfer = TransferTimer(
422
name="Maintenance Window Transfer",
423
schedule=once_schedule,
424
body=transfer_data
425
)
426
427
one_time_timer = timers_client.create_timer(maintenance_transfer)
428
print(f"Scheduled one-time transfer: {one_time_timer['timer']['id']}")
429
```
430
431
### Complex Recurring Schedules
432
433
```python
434
# Weekly backup with end date
435
weekly_schedule = RecurringTimerSchedule(
436
interval_seconds=7 * 24 * 60 * 60, # 7 days
437
start="2024-12-01T02:00:00Z",
438
end={"condition": "time", "datetime": "2025-12-01T02:00:00Z"}
439
)
440
441
# Monthly archive with execution limit
442
monthly_schedule = RecurringTimerSchedule(
443
interval_seconds=30 * 24 * 60 * 60, # 30 days
444
start="2024-12-01T00:00:00Z",
445
end={"condition": "iterations", "n": 12} # Run 12 times (1 year)
446
)
447
448
# Using convenience methods
449
hourly_sync = RecurringTimerSchedule.every_hour(
450
start="2024-12-01T00:00:00Z"
451
)
452
453
daily_report = RecurringTimerSchedule.every_day(
454
start="2024-12-01T06:00:00Z", # 6 AM daily
455
end={"condition": "iterations", "n": 365}
456
)
457
```
458
459
### Timer Management and Monitoring
460
461
```python
462
# List all timers
463
timers_list = timers_client.list_timers(limit=50)
464
for timer in timers_list["timers"]:
465
print(f"Timer: {timer['name']} ({timer['id']})")
466
print(f" Status: {timer['status']}")
467
print(f" Next run: {timer.get('next_run_time', 'N/A')}")
468
469
# Get detailed timer information
470
timer_details = timers_client.get_timer(timer_id)
471
print(f"Timer created: {timer_details['timer']['created_at']}")
472
print(f"Schedule: {timer_details['timer']['schedule']}")
473
474
# View execution history
475
executions = timers_client.get_timer_executions(timer_id, limit=10)
476
for execution in executions["executions"]:
477
print(f"Execution {execution['id']}: {execution['status']}")
478
if execution.get('completion_time'):
479
print(f" Completed: {execution['completion_time']}")
480
if execution.get('error_message'):
481
print(f" Error: {execution['error_message']}")
482
```
483
484
### Timer Control Operations
485
486
```python
487
# Pause timer temporarily
488
timers_client.pause_timer(timer_id)
489
print("Timer paused")
490
491
# Resume timer later
492
timers_client.resume_timer(timer_id)
493
print("Timer resumed")
494
495
# Update timer configuration
496
update_data = {
497
"name": "Updated Daily Backup Timer",
498
"schedule": {
499
"type": "recurring",
500
"interval_seconds": 12 * 60 * 60, # Change to every 12 hours
501
"start": "2024-12-01T02:00:00Z"
502
}
503
}
504
timers_client.update_timer(timer_id, update_data)
505
print("Timer schedule updated")
506
507
# Delete timer when no longer needed
508
timers_client.delete_timer(timer_id)
509
print("Timer deleted")
510
```
511
512
### Advanced Transfer Timer Patterns
513
514
```python
515
# Multi-path transfer timer
516
multi_transfer_data = TransferData(
517
source_endpoint="source-endpoint",
518
destination_endpoint="dest-endpoint",
519
label="Multi-Path Sync",
520
sync_level="checksum",
521
verify_checksum=True
522
)
523
524
# Add multiple transfer items
525
multi_transfer_data.add_item("/datasets/raw/", "/archive/raw/", recursive=True)
526
multi_transfer_data.add_item("/datasets/processed/", "/archive/processed/", recursive=True)
527
multi_transfer_data.add_item("/logs/", "/archive/logs/", recursive=True)
528
529
# Nightly sync timer
530
nightly_sync = TransferTimer(
531
name="Nightly Multi-Path Sync",
532
schedule=RecurringTimerSchedule.every_day(
533
start="2024-12-01T01:00:00Z" # 1 AM daily
534
),
535
body=multi_transfer_data
536
)
537
538
sync_timer = timers_client.create_timer(nightly_sync)
539
```
540
541
### Error Handling and Monitoring
542
543
```python
544
import time
545
546
def monitor_timer_execution(timers_client, timer_id, timeout=3600):
547
"""Monitor timer execution with error handling."""
548
549
start_time = time.time()
550
while time.time() - start_time < timeout:
551
try:
552
# Get recent executions
553
executions = timers_client.get_timer_executions(timer_id, limit=5)
554
555
for execution in executions["executions"]:
556
status = execution["status"]
557
558
if status == "completed":
559
print(f"Execution {execution['id']} completed successfully")
560
return True
561
elif status == "failed":
562
error_msg = execution.get("error_message", "Unknown error")
563
print(f"Execution {execution['id']} failed: {error_msg}")
564
565
# Get detailed execution info
566
exec_details = timers_client.get_execution(execution['id'])
567
print(f"Failure details: {exec_details.get('failure_reason', 'N/A')}")
568
return False
569
elif status in ["running", "pending"]:
570
print(f"Execution {execution['id']} is {status}")
571
572
time.sleep(30) # Wait before checking again
573
574
except Exception as e:
575
print(f"Error monitoring timer: {e}")
576
time.sleep(60)
577
578
print(f"Monitoring timeout after {timeout} seconds")
579
return False
580
581
# Usage
582
success = monitor_timer_execution(timers_client, timer_id)
583
```
584
585
### Integration with Other Services
586
587
```python
588
# Timer for periodic compute job execution
589
from globus_sdk import ComputeClientV3
590
591
# This would require custom integration as timers primarily support transfers
592
# Users would typically use Flows service to coordinate complex multi-service automation
593
594
# Timer triggering a flow execution (using webhook pattern)
595
webhook_timer_job = TimerJob(
596
name="Periodic Flow Trigger",
597
callback_url="https://flows.globus.org/webhook/trigger-flow",
598
interval=24 * 60 * 60, # Daily
599
start_time="2024-12-01T00:00:00Z"
600
)
601
602
# Note: This uses the legacy TimerJob class for webhook-based integration
603
webhook_timer = timers_client.create_job(webhook_timer_job)
604
```
605
606
### Conditional and Smart Scheduling
607
608
```python
609
# Create timer with smart end conditions
610
smart_schedule = RecurringTimerSchedule(
611
interval_seconds=60 * 60, # Every hour
612
start="2024-12-01T00:00:00Z",
613
end={
614
"condition": "time",
615
"datetime": "2025-01-01T00:00:00Z" # Stop after New Year
616
}
617
)
618
619
# Timer with execution count limit
620
limited_timer = RecurringTimerSchedule(
621
interval_seconds=6 * 60 * 60, # Every 6 hours
622
start="2024-12-01T00:00:00Z",
623
end={
624
"condition": "iterations",
625
"n": 100 # Run exactly 100 times then stop
626
}
627
)
628
629
# Business hours only timer (using specific start times)
630
business_hours_schedule = RecurringTimerSchedule(
631
interval_seconds=24 * 60 * 60, # Daily
632
start="2024-12-01T09:00:00-05:00", # 9 AM EST
633
end={"condition": "time", "datetime": "2025-12-01T09:00:00-05:00"}
634
)
635
```