evrblk 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -5
  3. data/README.md +2 -4
  4. data/evrblk.gemspec +14 -12
  5. data/lib/evrblk/authn/alfa.rb +9 -9
  6. data/lib/evrblk/authn/base.rb +5 -11
  7. data/lib/evrblk/authn/bravo.rb +7 -6
  8. data/lib/evrblk/authn/request_signer.rb +14 -15
  9. data/lib/evrblk/grackle/v1beta/api_pb.rb +123 -0
  10. data/lib/evrblk/grackle/v1beta/api_services_pb.rb +69 -0
  11. data/lib/evrblk/grackle/v1beta/client.rb +235 -0
  12. data/lib/evrblk/hash_converter.rb +26 -27
  13. data/lib/evrblk/moab/v0/api_pb.rb +71 -0
  14. data/lib/evrblk/moab/v0/api_services_pb.rb +43 -0
  15. data/lib/evrblk/moab/{preview → v0}/client.rb +30 -20
  16. data/lib/evrblk/version.rb +1 -1
  17. data/lib/evrblk.rb +6 -15
  18. data/proto/evrblk/grackle/v1beta/api.proto +886 -0
  19. data/proto/{moab/preview → evrblk/moab/v0}/api.proto +93 -16
  20. metadata +12 -21
  21. data/lib/evrblk/grackle/preview/api_pb.rb +0 -71
  22. data/lib/evrblk/grackle/preview/api_services_pb.rb +0 -48
  23. data/lib/evrblk/grackle/preview/client.rb +0 -126
  24. data/lib/evrblk/iam/preview/api_pb.rb +0 -56
  25. data/lib/evrblk/iam/preview/api_services_pb.rb +0 -39
  26. data/lib/evrblk/iam/preview/client.rb +0 -81
  27. data/lib/evrblk/moab/preview/api_pb.rb +0 -63
  28. data/lib/evrblk/moab/preview/api_services_pb.rb +0 -41
  29. data/lib/evrblk/myaccount/preview/api_pb.rb +0 -25
  30. data/lib/evrblk/myaccount/preview/api_services_pb.rb +0 -26
  31. data/lib/evrblk/myaccount/preview/client.rb +0 -17
  32. data/proto/grackle/preview/api.proto +0 -325
  33. data/proto/iam/preview/api.proto +0 -230
  34. data/proto/myaccount/preview/api.proto +0 -68
  35. data/protogen.sh +0 -6
@@ -0,0 +1,886 @@
1
+ syntax = "proto3";
2
+
3
+ package com.evrblk.grackle.v1beta;
4
+
5
+ option go_package = "github.com/evrblk/evrblk-go/grackle/v1beta;grackle";
6
+ option ruby_package = "Evrblk::Grackle::V1Beta";
7
+
8
+ service GrackleApi {
9
+ rpc CreateNamespace(CreateNamespaceRequest) returns (CreateNamespaceResponse) {}
10
+ rpc ListNamespaces(ListNamespacesRequest) returns (ListNamespacesResponse) {}
11
+ rpc GetNamespace(GetNamespaceRequest) returns (GetNamespaceResponse) {}
12
+ rpc DeleteNamespace(DeleteNamespaceRequest) returns (DeleteNamespaceResponse) {}
13
+ rpc UpdateNamespace(UpdateNamespaceRequest) returns (UpdateNamespaceResponse) {}
14
+
15
+ rpc CreateSemaphore(CreateSemaphoreRequest) returns (CreateSemaphoreResponse) {}
16
+ rpc ListSemaphores(ListSemaphoresRequest) returns (ListSemaphoresResponse) {}
17
+ rpc GetSemaphore(GetSemaphoreRequest) returns (GetSemaphoreResponse) {}
18
+ rpc AcquireSemaphore(AcquireSemaphoreRequest) returns (AcquireSemaphoreResponse) {}
19
+ rpc ReleaseSemaphore(ReleaseSemaphoreRequest) returns (ReleaseSemaphoreResponse) {}
20
+ rpc UpdateSemaphore(UpdateSemaphoreRequest) returns (UpdateSemaphoreResponse) {}
21
+ rpc DeleteSemaphore(DeleteSemaphoreRequest) returns (DeleteSemaphoreResponse) {}
22
+ rpc ListSemaphoreHolders(ListSemaphoreHoldersRequest) returns (ListSemaphoreHoldersResponse) {}
23
+ rpc CreateSemaphoreLease(CreateSemaphoreLeaseRequest) returns (CreateSemaphoreLeaseResponse) {}
24
+ rpc RevokeSemaphoreLease(RevokeSemaphoreLeaseRequest) returns (RevokeSemaphoreLeaseResponse) {}
25
+ rpc RefreshSemaphoreLease(RefreshSemaphoreLeaseRequest) returns (RefreshSemaphoreLeaseResponse) {}
26
+ rpc ListSemaphoreLeases(ListSemaphoreLeasesRequest) returns (ListSemaphoreLeasesResponse) {}
27
+ rpc GetSemaphoreLease(GetSemaphoreLeaseRequest) returns (GetSemaphoreLeaseResponse) {}
28
+
29
+ rpc CreateWaitGroup(CreateWaitGroupRequest) returns (CreateWaitGroupResponse) {}
30
+ rpc UpdateWaitGroup(UpdateWaitGroupRequest) returns (UpdateWaitGroupResponse) {}
31
+ rpc ListWaitGroups(ListWaitGroupsRequest) returns (ListWaitGroupsResponse) {}
32
+ rpc GetWaitGroup(GetWaitGroupRequest) returns (GetWaitGroupResponse) {}
33
+ rpc DeleteWaitGroup(DeleteWaitGroupRequest) returns (DeleteWaitGroupResponse) {}
34
+ rpc CompleteJobsFromWaitGroup(CompleteJobsFromWaitGroupRequest) returns (CompleteJobsFromWaitGroupResponse) {}
35
+ rpc ListWaitGroupCompletedJobs(ListWaitGroupCompletedJobsRequest) returns (ListWaitGroupCompletedJobsResponse) {}
36
+ rpc WaitForWaitGroup(WaitForWaitGroupRequest) returns (WaitForWaitGroupResponse) {}
37
+
38
+ rpc AcquireLock(AcquireLockRequest) returns (AcquireLockResponse) {}
39
+ rpc ReleaseLock(ReleaseLockRequest) returns (ReleaseLockResponse) {}
40
+ rpc GetLock(GetLockRequest) returns (GetLockResponse) {}
41
+ rpc DeleteLock(DeleteLockRequest) returns (DeleteLockResponse) {}
42
+ rpc ListLocks(ListLocksRequest) returns (ListLocksResponse) {}
43
+ rpc CreateLockLease(CreateLockLeaseRequest) returns (CreateLockLeaseResponse) {}
44
+ rpc RevokeLockLease(RevokeLockLeaseRequest) returns (RevokeLockLeaseResponse) {}
45
+ rpc RefreshLockLease(RefreshLockLeaseRequest) returns (RefreshLockLeaseResponse) {}
46
+ rpc ListLockLeases(ListLockLeasesRequest) returns (ListLockLeasesResponse) {}
47
+ rpc GetLockLease(GetLockLeaseRequest) returns (GetLockLeaseResponse) {}
48
+
49
+ rpc CreateBarrier(CreateBarrierRequest) returns (CreateBarrierResponse) {}
50
+ rpc ListBarriers(ListBarriersRequest) returns (ListBarriersResponse) {}
51
+ rpc GetBarrier(GetBarrierRequest) returns (GetBarrierResponse) {}
52
+ rpc DeleteBarrier(DeleteBarrierRequest) returns (DeleteBarrierResponse) {}
53
+ rpc UpdateBarrier(UpdateBarrierRequest) returns (UpdateBarrierResponse) {}
54
+ rpc ArriveAtBarrier(ArriveAtBarrierRequest) returns (ArriveAtBarrierResponse) {}
55
+ rpc WaitAtBarrier(WaitAtBarrierRequest) returns (WaitAtBarrierResponse) {}
56
+ rpc ListBarrierParticipants(ListBarrierParticipantsRequest) returns (ListBarrierParticipantsResponse) {}
57
+ }
58
+
59
+ message CreateNamespaceRequest {
60
+ string name = 1;
61
+ string description = 2;
62
+ map<string, string> metadata = 3;
63
+ }
64
+
65
+ message CreateNamespaceResponse {
66
+ Namespace namespace = 1;
67
+ }
68
+
69
+ message ListNamespacesRequest {
70
+ string pagination_token = 1;
71
+ int32 limit = 2;
72
+ }
73
+
74
+ message ListNamespacesResponse {
75
+ repeated Namespace namespaces = 1;
76
+ string next_pagination_token = 2;
77
+ string previous_pagination_token = 3;
78
+ }
79
+
80
+ message GetNamespaceRequest {
81
+ string namespace_name = 1;
82
+ }
83
+
84
+ message GetNamespaceResponse {
85
+ Namespace namespace = 1;
86
+ }
87
+
88
+ message DeleteNamespaceRequest {
89
+ string namespace_name = 1;
90
+ }
91
+
92
+ message DeleteNamespaceResponse {}
93
+
94
+ message UpdateNamespaceRequest {
95
+ string namespace_name = 1;
96
+ string description = 2;
97
+ map<string, string> metadata = 3;
98
+ // Optimistic concurrency: must equal the namespace's current version or the
99
+ // update is rejected.
100
+ int64 expected_version = 4;
101
+ }
102
+
103
+ message UpdateNamespaceResponse {
104
+ Namespace namespace = 1;
105
+ }
106
+
107
+ message CreateSemaphoreRequest {
108
+ string namespace_name = 1;
109
+ string semaphore_name = 2;
110
+ string description = 3;
111
+ // Total capacity: the maximum sum of holder weights that can be held at once.
112
+ int64 permits = 4;
113
+ map<string, string> metadata = 5;
114
+ }
115
+
116
+ message CreateSemaphoreResponse {
117
+ Semaphore semaphore = 1;
118
+ }
119
+
120
+ message ListSemaphoresRequest {
121
+ string namespace_name = 1;
122
+ string pagination_token = 2;
123
+ int32 limit = 3;
124
+ }
125
+
126
+ message ListSemaphoresResponse {
127
+ repeated Semaphore semaphores = 1;
128
+ string next_pagination_token = 2;
129
+ string previous_pagination_token = 3;
130
+ }
131
+
132
+ message GetSemaphoreRequest {
133
+ string namespace_name = 1;
134
+ string semaphore_name = 2;
135
+ }
136
+
137
+ message GetSemaphoreResponse {
138
+ Semaphore semaphore = 1;
139
+ }
140
+
141
+ message AcquireSemaphoreRequest {
142
+ string namespace_name = 1;
143
+ string semaphore_name = 2;
144
+ // Lease the permits are acquired under; the hold is released when this lease is
145
+ // released, revoked, or expires. Re-acquiring under the same lease adjusts the
146
+ // existing hold's weight rather than creating a second hold.
147
+ string lease_id = 3;
148
+ // Number of permits to acquire. The acquire is all-or-nothing: it succeeds only
149
+ // when weight permits are free. Must be > 0 and <= the semaphore's permits.
150
+ int64 weight = 4;
151
+ // How long to block waiting for permits to become available. 0 returns
152
+ // immediately (non-blocking try); see AcquireOutcome.
153
+ int32 timeout_seconds = 5;
154
+ map<string, string> metadata = 6;
155
+ }
156
+
157
+ message AcquireSemaphoreResponse {
158
+ Semaphore semaphore = 1;
159
+ AcquireOutcome outcome = 2;
160
+ }
161
+
162
+ // AcquireOutcome is the terminal result of an AcquireLock or AcquireSemaphore
163
+ // call. These outcomes describe a request that was valid and processed —
164
+ // malformed requests (bad lease id, weight <= 0, weight exceeding permits) and
165
+ // missing resources are reported as gRPC errors (InvalidArgument / NotFound),
166
+ // never as an outcome.
167
+ enum AcquireOutcome {
168
+ ACQUIRE_OUTCOME_INVALID = 0;
169
+ // ACQUIRED: the lease now holds the lock/semaphore.
170
+ ACQUIRE_OUTCOME_ACQUIRED = 1;
171
+ // UNAVAILABLE: a non-blocking attempt (timeout_seconds = 0) found the
172
+ // primitive held by someone else and returned without waiting.
173
+ ACQUIRE_OUTCOME_UNAVAILABLE = 2;
174
+ // TIMED_OUT: the call blocked until timeout_seconds elapsed without the
175
+ // primitive ever becoming available.
176
+ ACQUIRE_OUTCOME_TIMED_OUT = 3;
177
+ }
178
+
179
+ message ReleaseSemaphoreRequest {
180
+ string namespace_name = 1;
181
+ string semaphore_name = 2;
182
+ string lease_id = 3;
183
+ }
184
+
185
+ message ReleaseSemaphoreResponse {
186
+ Semaphore semaphore = 1;
187
+ }
188
+
189
+ message UpdateSemaphoreRequest {
190
+ string namespace_name = 1;
191
+ string semaphore_name = 2;
192
+ string description = 3;
193
+ // New total capacity. Cannot be lowered below the permits currently held
194
+ // (active_holds).
195
+ int64 permits = 4;
196
+ map<string, string> metadata = 5;
197
+ // Optimistic concurrency: must equal the semaphore's current version or the
198
+ // update is rejected.
199
+ int64 expected_version = 6;
200
+ }
201
+
202
+ message UpdateSemaphoreResponse {
203
+ Semaphore semaphore = 1;
204
+ }
205
+
206
+ message DeleteSemaphoreRequest {
207
+ string namespace_name = 1;
208
+ string semaphore_name = 2;
209
+ }
210
+
211
+ message DeleteSemaphoreResponse {}
212
+
213
+ message ListSemaphoreHoldersRequest {
214
+ string namespace_name = 1;
215
+ string semaphore_name = 2;
216
+ string pagination_token = 3;
217
+ int32 limit = 4;
218
+ }
219
+
220
+ message ListSemaphoreHoldersResponse {
221
+ repeated SemaphoreHolder holders = 1;
222
+ string next_pagination_token = 2;
223
+ string previous_pagination_token = 3;
224
+ }
225
+
226
+ message CreateSemaphoreLeaseRequest {
227
+ string namespace_name = 1;
228
+ // Caller-supplied identifier of the owning process (free-form, e.g.
229
+ // "host-123/pid-4567"). Surfaced on holders for diagnostics.
230
+ string process_id = 2;
231
+ // Lease lifetime in seconds, measured from now. The lease (and everything held
232
+ // under it) is released automatically if not refreshed before it elapses.
233
+ int64 ttl_seconds = 3;
234
+ map<string, string> metadata = 4;
235
+ }
236
+
237
+ message CreateSemaphoreLeaseResponse {
238
+ Lease lease = 1;
239
+ }
240
+
241
+ message RevokeSemaphoreLeaseRequest {
242
+ string namespace_name = 1;
243
+ string lease_id = 2;
244
+ }
245
+
246
+ message RevokeSemaphoreLeaseResponse {}
247
+
248
+ message RefreshSemaphoreLeaseRequest {
249
+ string namespace_name = 1;
250
+ string lease_id = 2;
251
+ // New lifetime in seconds from now; extends the lease and every hold it owns.
252
+ int64 ttl_seconds = 3;
253
+ }
254
+
255
+ message RefreshSemaphoreLeaseResponse {
256
+ Lease lease = 1;
257
+ }
258
+
259
+ message ListSemaphoreLeasesRequest {
260
+ string namespace_name = 1;
261
+ string pagination_token = 2;
262
+ int32 limit = 3;
263
+ }
264
+
265
+ message ListSemaphoreLeasesResponse {
266
+ repeated Lease leases = 1;
267
+ string next_pagination_token = 2;
268
+ string previous_pagination_token = 3;
269
+ }
270
+
271
+ message GetSemaphoreLeaseRequest {
272
+ string namespace_name = 1;
273
+ string lease_id = 2;
274
+ }
275
+
276
+ message GetSemaphoreLeaseResponse {
277
+ Lease lease = 1;
278
+ }
279
+
280
+ // Lease is a time-bounded ownership token. It is the unit that holds locks and
281
+ // semaphore permits: a client creates a lease, then acquires locks/semaphores
282
+ // under it, and must keep it alive by refreshing before it expires (a heartbeat).
283
+ // When a lease expires or is revoked, the server automatically releases
284
+ // everything held under it — so a crashed client never leaves dangling holds.
285
+ // Locks and semaphores use separate leases (CreateLockLease vs
286
+ // CreateSemaphoreLease) and a lease is scoped to a single namespace.
287
+ message Lease {
288
+ string lease_id = 1;
289
+ // Caller-supplied identifier of the owning process (free-form). Server does not
290
+ // interpret it; it is echoed back for diagnostics.
291
+ string process_id = 2;
292
+ // Creation time, Unix nanoseconds.
293
+ int64 created_at = 3;
294
+ // Absolute expiration time, Unix nanoseconds. Once the server clock passes this,
295
+ // the lease and all holds under it are released. Push it forward with
296
+ // Refresh{Lock,Semaphore}Lease.
297
+ int64 expires_at = 4;
298
+ map<string, string> metadata = 5;
299
+ }
300
+
301
+ // Semaphore is a weighted counting semaphore: it admits concurrent holders as
302
+ // long as the sum of their weights stays within permits. Holders are leases;
303
+ // expired holders are pruned, so the active_* fields always reflect only holders
304
+ // whose leases are still valid.
305
+ message Semaphore {
306
+ string name = 1;
307
+ string description = 2;
308
+ // Creation / last-modification time, Unix nanoseconds.
309
+ int64 created_at = 3;
310
+ int64 updated_at = 4;
311
+ // Monotonic version, bumped on every successful update. Pass as expected_version
312
+ // in UpdateSemaphore for optimistic concurrency control.
313
+ int64 version = 5;
314
+ // Total capacity (maximum sum of holder weights held at once).
315
+ int64 permits = 6;
316
+ // Currently consumed capacity: the sum of all active holders' weights
317
+ // (0 <= active_holds <= permits).
318
+ int64 active_holds = 7;
319
+ // Number of distinct leases currently holding permits.
320
+ int64 active_holders_count = 8;
321
+ map<string, string> metadata = 9;
322
+ // Time of the most recent acquire attempt (successful or not), Unix nanoseconds.
323
+ // Useful for reaping idle semaphores.
324
+ int64 last_activity_at = 10;
325
+ }
326
+
327
+ // SemaphoreHolder is one lease's hold on a semaphore (see ListSemaphoreHolders).
328
+ message SemaphoreHolder {
329
+ // The lease holding these permits.
330
+ string lease_id = 1;
331
+ // When the hold was acquired, Unix nanoseconds.
332
+ int64 locked_at = 2;
333
+ // Number of permits this holder consumes.
334
+ int64 weight = 3;
335
+ map<string, string> metadata = 4;
336
+ }
337
+
338
+ message CreateWaitGroupRequest {
339
+ string namespace_name = 1;
340
+ string wait_group_name = 2;
341
+ string description = 3;
342
+ // Total number of jobs that must complete before the group is COMPLETED.
343
+ int64 counter = 4;
344
+ // Absolute deadline, Unix nanoseconds. If the group has not completed by then it
345
+ // becomes EXPIRED.
346
+ int64 expires_at = 5;
347
+ map<string, string> metadata = 6;
348
+ // Retention after finishing: the group is automatically deleted this many
349
+ // seconds after it finishes (completes or expires).
350
+ int64 delete_after_finished_seconds = 7;
351
+ }
352
+
353
+ message CreateWaitGroupResponse {
354
+ WaitGroup wait_group = 1;
355
+ }
356
+
357
+ message UpdateWaitGroupRequest {
358
+ string namespace_name = 1;
359
+ string wait_group_name = 2;
360
+ string description = 3;
361
+ // New total number of jobs required to complete the group.
362
+ int64 counter = 4;
363
+ // New absolute deadline, Unix nanoseconds.
364
+ int64 expires_at = 5;
365
+ map<string, string> metadata = 6;
366
+ // Optimistic concurrency: must equal the wait group's current version or the
367
+ // update is rejected.
368
+ int64 expected_version = 7;
369
+ // New retention period (seconds after finishing) before automatic deletion.
370
+ int64 delete_after_finished_seconds = 8;
371
+ }
372
+
373
+ message UpdateWaitGroupResponse {
374
+ WaitGroup wait_group = 1;
375
+ }
376
+
377
+ message ListWaitGroupsRequest {
378
+ string namespace_name = 1;
379
+ string pagination_token = 2;
380
+ int32 limit = 3;
381
+ }
382
+
383
+ message ListWaitGroupsResponse {
384
+ repeated WaitGroup wait_groups = 1;
385
+ string next_pagination_token = 2;
386
+ string previous_pagination_token = 3;
387
+ }
388
+
389
+ message GetWaitGroupRequest {
390
+ string namespace_name = 1;
391
+ string wait_group_name = 2;
392
+ }
393
+
394
+ message GetWaitGroupResponse {
395
+ WaitGroup wait_group = 1;
396
+ }
397
+
398
+ message DeleteWaitGroupRequest {
399
+ string namespace_name = 1;
400
+ string wait_group_name = 2;
401
+ }
402
+
403
+ message DeleteWaitGroupResponse {}
404
+
405
+ message CompleteJobsFromWaitGroupRequest {
406
+ string namespace_name = 1;
407
+ string wait_group_name = 2;
408
+ repeated CompleteJobRequest jobs = 3;
409
+ }
410
+
411
+ message CompleteJobRequest {
412
+ // Caller-chosen identifier of the completed job. Completion is idempotent per
413
+ // job_id: completing the same id twice counts once, so retries are safe.
414
+ string job_id = 1;
415
+ map<string, string> metadata = 2;
416
+ }
417
+
418
+ message CompleteJobsFromWaitGroupResponse {
419
+ WaitGroup wait_group = 1;
420
+ }
421
+
422
+ message ListWaitGroupCompletedJobsRequest {
423
+ string namespace_name = 1;
424
+ string wait_group_name = 2;
425
+ string pagination_token = 3;
426
+ int32 limit = 4;
427
+ }
428
+
429
+ message ListWaitGroupCompletedJobsResponse {
430
+ repeated WaitGroupJob jobs = 1;
431
+ string next_pagination_token = 2;
432
+ string previous_pagination_token = 3;
433
+ }
434
+
435
+ message WaitForWaitGroupRequest {
436
+ string namespace_name = 1;
437
+ string wait_group_name = 2;
438
+ // How long to block waiting for the group to finish. 0 returns immediately with
439
+ // the current state; see WaitGroupWaitOutcome.
440
+ int32 timeout_seconds = 3;
441
+ }
442
+
443
+ message WaitForWaitGroupResponse {
444
+ WaitGroup wait_group = 1;
445
+ WaitGroupWaitOutcome outcome = 2;
446
+ }
447
+
448
+ // WaitGroupWaitOutcome is the terminal result of a WaitForWaitGroup call. The
449
+ // wait group's intrinsic lifecycle state is also available on
450
+ // WaitGroup.status; this outcome reports why this particular call returned.
451
+ enum WaitGroupWaitOutcome {
452
+ WAIT_GROUP_WAIT_OUTCOME_INVALID = 0;
453
+ // COMPLETED: all jobs were completed.
454
+ WAIT_GROUP_WAIT_OUTCOME_COMPLETED = 1;
455
+ // EXPIRED: the wait group's expires_at passed while still active.
456
+ WAIT_GROUP_WAIT_OUTCOME_EXPIRED = 2;
457
+ // TIMED_OUT: timeout_seconds elapsed while the wait group was still active.
458
+ WAIT_GROUP_WAIT_OUTCOME_TIMED_OUT = 3;
459
+ }
460
+
461
+ // WaitGroup tracks completion of a fixed set of jobs — a distributed, durable
462
+ // sync.WaitGroup for fan-in of up to millions of jobs. It starts with counter
463
+ // jobs outstanding; each job reported via CompleteJobsFromWaitGroup increments
464
+ // completed_jobs, and the group becomes COMPLETED once completed_jobs reaches
465
+ // counter (or EXPIRED if expires_at passes first). WaitForWaitGroup blocks until
466
+ // it finishes.
467
+ message WaitGroup {
468
+ string name = 1;
469
+ string description = 2;
470
+ // Creation / last-modification time, Unix nanoseconds.
471
+ int64 created_at = 3;
472
+ int64 updated_at = 4;
473
+ // Monotonic version, bumped on every successful update. Pass as expected_version
474
+ // in UpdateWaitGroup for optimistic concurrency control.
475
+ int64 version = 5;
476
+ // Absolute deadline, Unix nanoseconds; the group becomes EXPIRED if it has not
477
+ // completed by then.
478
+ int64 expires_at = 6;
479
+ // Total number of jobs required to complete the group.
480
+ int64 counter = 7;
481
+ // Number of distinct jobs completed so far (0 <= completed_jobs <= counter).
482
+ int64 completed_jobs = 8;
483
+ map<string, string> metadata = 9;
484
+ WaitGroupStatus status = 10;
485
+ // Retention period: the group is automatically deleted this many seconds after
486
+ // finished_at.
487
+ int64 delete_after_finished_seconds = 11;
488
+ // When the group finished (reached COMPLETED or EXPIRED), Unix nanoseconds; 0
489
+ // while still ACTIVE.
490
+ int64 finished_at = 12;
491
+ // Time of the most recent activity (e.g. a job completion), Unix nanoseconds.
492
+ int64 last_activity_at = 13;
493
+ }
494
+
495
+ // WaitGroupStatus is the lifecycle state of a wait group. A wait group starts
496
+ // ACTIVE, becomes COMPLETED once all jobs are completed, or EXPIRED once
497
+ // expires_at passes while still active. Finished (COMPLETED or EXPIRED) wait
498
+ // groups are deleted automatically once delete_after_finished_seconds elapses.
499
+ enum WaitGroupStatus {
500
+ WAIT_GROUP_STATUS_INVALID = 0;
501
+ WAIT_GROUP_STATUS_ACTIVE = 1;
502
+ WAIT_GROUP_STATUS_EXPIRED = 2;
503
+ WAIT_GROUP_STATUS_COMPLETED = 3;
504
+ }
505
+
506
+ // WaitGroupJob is one completed job recorded against a wait group (see
507
+ // ListWaitGroupCompletedJobs).
508
+ message WaitGroupJob {
509
+ string job_id = 1;
510
+ // When the job was reported complete, Unix nanoseconds.
511
+ int64 completed_at = 2;
512
+ map<string, string> metadata = 3;
513
+ }
514
+
515
+ message AcquireLockRequest {
516
+ string namespace_name = 1;
517
+ // Lock name, a '/'-separated path (e.g. "users/123/profile"). Paths form a
518
+ // hierarchy: a lock conflicts with locks on its ancestor and descendant paths
519
+ // (see Lock), so guarding a subtree does not require enumerating every leaf.
520
+ string lock_name = 2;
521
+ // true acquires the lock exclusively (one holder); false acquires it shared
522
+ // (multiple shared holders coexist, but block exclusive acquirers).
523
+ bool exclusive = 3;
524
+ // Lease the lock is held under; the lock is released when this lease is
525
+ // released, revoked, or expires. Re-acquiring under a lease that already holds
526
+ // the lock just refreshes it.
527
+ string lease_id = 4;
528
+ // How long to block waiting for the lock. 0 returns immediately (non-blocking
529
+ // try); see AcquireOutcome.
530
+ int32 timeout_seconds = 5;
531
+ map<string, string> metadata = 6;
532
+ }
533
+
534
+ message AcquireLockResponse {
535
+ Lock lock = 1;
536
+ AcquireOutcome outcome = 2;
537
+ // When outcome is not ACQUIRED, a best-effort hint at what the lock was
538
+ // blocked on. Diagnostic only: it is a point-in-time snapshot of the last
539
+ // acquire attempt and may be stale by the time it is read, so clients must
540
+ // not build control flow on it. UNSPECIFIED when the lock was acquired.
541
+ ContentionReason reason = 3;
542
+ // The locks currently blocking this acquire, to show the caller what stands
543
+ // in the way: the blocking ancestor lock(s) (ANCESTOR) or blocking descendant
544
+ // locks (DESCENDANT). Empty for PEER — there the conflicting lock is the one
545
+ // being acquired, already returned in the lock field above, so it is not
546
+ // duplicated here. Like reason this is a best-effort, point-in-time snapshot
547
+ // and may be stale. It is always bounded — at most 50 locks are returned (a
548
+ // descendant subtree may hold more) — so it is cheap and safe to read. Empty
549
+ // when the lock was acquired.
550
+ repeated Lock blocking_locks = 4;
551
+ }
552
+
553
+ // ContentionReason explains why an AcquireLock attempt found the lock
554
+ // unavailable. Locks form a '/'-separated hierarchy (see Lock), so a request
555
+ // can be blocked by the lock itself, by an ancestor path, or by a descendant
556
+ // path. This is a diagnostic hint, not part of the acquire control flow —
557
+ // branch on AcquireOutcome, not on this.
558
+ enum ContentionReason {
559
+ CONTENTION_REASON_UNSPECIFIED = 0;
560
+ // PEER: the lock itself is held in an incompatible mode by another lease
561
+ // (held shared while exclusive was requested, or held exclusively).
562
+ CONTENTION_REASON_PEER = 1;
563
+ // ANCESTOR: a lock on an ancestor path blocks this acquire.
564
+ CONTENTION_REASON_ANCESTOR = 2;
565
+ // DESCENDANT: one or more locks on descendant paths block this acquire.
566
+ CONTENTION_REASON_DESCENDANT = 3;
567
+ }
568
+
569
+ message ReleaseLockRequest {
570
+ string namespace_name = 1;
571
+ string lock_name = 2;
572
+ string lease_id = 3;
573
+ }
574
+
575
+ message ReleaseLockResponse {
576
+ Lock lock = 1;
577
+ }
578
+
579
+ message GetLockRequest {
580
+ string namespace_name = 1;
581
+ string lock_name = 2;
582
+ }
583
+
584
+ message GetLockResponse {
585
+ Lock lock = 1;
586
+ }
587
+
588
+ message DeleteLockRequest {
589
+ string namespace_name = 1;
590
+ string lock_name = 2;
591
+ }
592
+
593
+ message DeleteLockResponse {}
594
+
595
+ message ListLocksRequest {
596
+ string namespace_name = 1;
597
+ string pagination_token = 2;
598
+ int32 limit = 3;
599
+ }
600
+
601
+ message ListLocksResponse {
602
+ repeated Lock locks = 1;
603
+ string next_pagination_token = 2;
604
+ string previous_pagination_token = 3;
605
+ }
606
+
607
+ message CreateLockLeaseRequest {
608
+ string namespace_name = 1;
609
+ // Caller-supplied identifier of the owning process (free-form). Surfaced on lock
610
+ // holders for diagnostics.
611
+ string process_id = 2;
612
+ // Lease lifetime in seconds, measured from now. The lease (and every lock held
613
+ // under it) is released automatically if not refreshed before it elapses.
614
+ int64 ttl_seconds = 3;
615
+ map<string, string> metadata = 4;
616
+ }
617
+
618
+ message CreateLockLeaseResponse {
619
+ Lease lease = 1;
620
+ }
621
+
622
+ message RevokeLockLeaseRequest {
623
+ string namespace_name = 1;
624
+ string lease_id = 2;
625
+ }
626
+
627
+ message RevokeLockLeaseResponse {}
628
+
629
+ message RefreshLockLeaseRequest {
630
+ string namespace_name = 1;
631
+ string lease_id = 2;
632
+ // New lifetime in seconds from now; extends the lease and every lock it holds.
633
+ int64 ttl_seconds = 3;
634
+ }
635
+
636
+ message RefreshLockLeaseResponse {
637
+ Lease lease = 1;
638
+ }
639
+
640
+ message ListLockLeasesRequest {
641
+ string namespace_name = 1;
642
+ string pagination_token = 2;
643
+ int32 limit = 3;
644
+ }
645
+
646
+ message ListLockLeasesResponse {
647
+ repeated Lease leases = 1;
648
+ string next_pagination_token = 2;
649
+ string previous_pagination_token = 3;
650
+ }
651
+
652
+ message GetLockLeaseRequest {
653
+ string namespace_name = 1;
654
+ string lease_id = 2;
655
+ }
656
+
657
+ message GetLockLeaseResponse {
658
+ Lease lease = 1;
659
+ }
660
+
661
+ // Lock is a distributed read/write (shared/exclusive) lock, held under a lease.
662
+ // Locks are not created explicitly: the first successful AcquireLock creates the
663
+ // lock, and it disappears once no holders remain. A lock can have many shared
664
+ // holders at once, or a single exclusive holder, never both.
665
+ //
666
+ // Lock names are '/'-separated paths and form a hierarchy. An exclusive lock at
667
+ // any path conflicts with acquires on its ancestors and descendants; a shared
668
+ // lock blocks only exclusive acquires up and down the path. Sibling paths are
669
+ // independent. This lets a caller guard a whole subtree without locking every
670
+ // leaf — acquire root-to-leaf and release leaf-to-root to avoid deadlocks.
671
+ message Lock {
672
+ string name = 1;
673
+ LockState state = 2;
674
+ // When the lock first became held (by its current set of holders), Unix
675
+ // nanoseconds.
676
+ int64 locked_at = 3;
677
+ // The leases currently holding the lock: exactly one when EXCLUSIVE_LOCKED,
678
+ // one or more when SHARED_LOCKED, empty when UNLOCKED.
679
+ repeated LockHolder lock_holders = 4;
680
+ // Time of the most recent acquire attempt against this lock, Unix nanoseconds.
681
+ int64 last_activity_at = 5;
682
+ }
683
+
684
+ // LockHolder is one lease's hold on a lock.
685
+ message LockHolder {
686
+ // The lease holding the lock.
687
+ string lease_id = 1;
688
+ // When this holder acquired the lock, Unix nanoseconds.
689
+ int64 locked_at = 2;
690
+ map<string, string> metadata = 3;
691
+ }
692
+
693
+ // LockState is the current hold state of a lock.
694
+ enum LockState {
695
+ LOCK_STATE_INVALID = 0;
696
+ // No holders (the lock effectively does not exist).
697
+ LOCK_STATE_UNLOCKED = 1;
698
+ // Held shared by one or more leases; further shared acquires succeed, exclusive
699
+ // acquires block.
700
+ LOCK_STATE_SHARED_LOCKED = 2;
701
+ // Held exclusively by a single lease; all other acquires block.
702
+ LOCK_STATE_EXCLUSIVE_LOCKED = 3;
703
+ }
704
+
705
+ // Namespace is the container for all primitives (locks, semaphores, wait groups,
706
+ // barriers) and their leases. Names are unique per account, and every other API
707
+ // call is scoped to a namespace. Deleting a namespace asynchronously deletes
708
+ // everything inside it.
709
+ message Namespace {
710
+ string name = 1;
711
+ string description = 2;
712
+ // Creation / last-modification time, Unix nanoseconds.
713
+ int64 created_at = 3;
714
+ int64 updated_at = 4;
715
+ // Monotonic version, bumped on every successful update. Pass as expected_version
716
+ // in UpdateNamespace for optimistic concurrency control.
717
+ int64 version = 5;
718
+ map<string, string> metadata = 6;
719
+ }
720
+
721
+ message CreateBarrierRequest {
722
+ string namespace_name = 1;
723
+ string barrier_name = 2;
724
+ string description = 3;
725
+ // Number of processes that must arrive before the barrier trips (releases) for
726
+ // a generation.
727
+ int64 expected_processes = 4;
728
+ // The barrier is automatically deleted this many seconds after its last
729
+ // activity (creation or an arrival).
730
+ int64 delete_inactive_after_seconds = 8;
731
+ map<string, string> metadata = 9;
732
+ }
733
+
734
+ message CreateBarrierResponse {
735
+ Barrier barrier = 1;
736
+ }
737
+
738
+ message ListBarriersRequest {
739
+ string namespace_name = 1;
740
+ string pagination_token = 2;
741
+ int32 limit = 3;
742
+ }
743
+
744
+ message ListBarriersResponse {
745
+ repeated Barrier barriers = 1;
746
+ string next_pagination_token = 2;
747
+ string previous_pagination_token = 3;
748
+ }
749
+
750
+ message GetBarrierRequest {
751
+ string namespace_name = 1;
752
+ string barrier_name = 2;
753
+ }
754
+
755
+ message GetBarrierResponse {
756
+ Barrier barrier = 1;
757
+ }
758
+
759
+ message DeleteBarrierRequest {
760
+ string namespace_name = 1;
761
+ string barrier_name = 2;
762
+ }
763
+
764
+ message DeleteBarrierResponse {}
765
+
766
+ message UpdateBarrierRequest {
767
+ string namespace_name = 1;
768
+ string barrier_name = 2;
769
+ string description = 3;
770
+ // New number of processes required to trip the barrier.
771
+ int64 expected_processes = 4;
772
+ map<string, string> metadata = 5;
773
+ // Optimistic concurrency: must equal the barrier's current version or the update
774
+ // is rejected.
775
+ int64 expected_version = 6;
776
+ // New inactivity period (seconds) before automatic deletion.
777
+ int64 delete_inactive_after_seconds = 7;
778
+ }
779
+
780
+ message UpdateBarrierResponse {
781
+ Barrier barrier = 1;
782
+ }
783
+
784
+ message ArriveAtBarrierRequest {
785
+ string namespace_name = 1;
786
+ string barrier_name = 2;
787
+ // Identifier of the arriving process. Arrival is idempotent per
788
+ // (generation, process_id): the same process arriving twice in a generation
789
+ // counts once.
790
+ string process_id = 3;
791
+ // The generation the caller is arriving for; must match the barrier's current
792
+ // generation, otherwise the call is rejected (guards against contributing to
793
+ // the wrong cycle).
794
+ int64 expected_generation = 4;
795
+ map<string, string> metadata = 5;
796
+ }
797
+
798
+ message ArriveAtBarrierResponse {
799
+ Barrier barrier = 1;
800
+ // true if this arrival was the last one needed and the barrier tripped (its
801
+ // generation has now advanced and arrived_processes reset to 0).
802
+ bool all_arrived = 2;
803
+ }
804
+
805
+ message WaitAtBarrierRequest {
806
+ string namespace_name = 1;
807
+ string barrier_name = 2;
808
+ // The generation the caller is waiting on. The call returns once the barrier
809
+ // advances past it (trips). Waiting on a generation that has already passed
810
+ // returns immediately. WaitAtBarrier does not itself register an arrival.
811
+ int64 expected_generation = 3;
812
+ // How long to block waiting for the barrier to trip. 0 returns immediately; see
813
+ // BarrierWaitOutcome.
814
+ int32 timeout_seconds = 4;
815
+ }
816
+
817
+ message WaitAtBarrierResponse {
818
+ Barrier barrier = 1;
819
+ BarrierWaitOutcome outcome = 2;
820
+ }
821
+
822
+ // BarrierWaitOutcome is the terminal result of a WaitAtBarrier call.
823
+ enum BarrierWaitOutcome {
824
+ BARRIER_WAIT_OUTCOME_INVALID = 0;
825
+ // TRIPPED: all expected processes arrived and the barrier advanced to the
826
+ // next generation.
827
+ BARRIER_WAIT_OUTCOME_TRIPPED = 1;
828
+ // TIMED_OUT: timeout_seconds elapsed before the barrier tripped.
829
+ BARRIER_WAIT_OUTCOME_TIMED_OUT = 2;
830
+ }
831
+
832
+ message ListBarrierParticipantsRequest {
833
+ string namespace_name = 1;
834
+ string barrier_name = 2;
835
+ // Which generation's arrivals to list (participant records are kept per
836
+ // generation).
837
+ int64 generation = 3;
838
+ string pagination_token = 4;
839
+ int32 limit = 5;
840
+ }
841
+
842
+ message ListBarrierParticipantsResponse {
843
+ repeated BarrierParticipant participants = 1;
844
+ string next_pagination_token = 2;
845
+ string previous_pagination_token = 3;
846
+ }
847
+
848
+ // Barrier is a reusable, generational rendezvous point for a fixed number of
849
+ // processes (like a cyclic barrier). Processes call ArriveAtBarrier; once
850
+ // expected_processes of them have arrived, the barrier "trips": all waiters are
851
+ // released, generation advances by one, and arrived_processes resets to 0 for
852
+ // the next cycle. The generation lets a fast process wait for exactly the cycle
853
+ // it cares about and a slow one avoid contributing to the wrong cycle.
854
+ message Barrier {
855
+ string name = 1;
856
+ string description = 2;
857
+ // Number of arrivals required to trip the barrier.
858
+ int64 expected_processes = 3;
859
+ // Arrivals recorded in the current generation so far (0 <= arrived_processes <
860
+ // expected_processes; reaching it trips the barrier and resets this to 0).
861
+ int64 arrived_processes = 4;
862
+ // Current cycle number, starting at 1 and incremented by exactly one on each
863
+ // trip.
864
+ int64 generation = 5;
865
+ // Creation / last-modification time, Unix nanoseconds.
866
+ int64 created_at = 6;
867
+ int64 updated_at = 7;
868
+ // Monotonic version, bumped on every successful update. Pass as expected_version
869
+ // in UpdateBarrier for optimistic concurrency control.
870
+ int64 version = 8;
871
+ map<string, string> metadata = 9;
872
+ // Time of the most recent activity (creation or an arrival), Unix nanoseconds.
873
+ // Drives inactivity-based auto-deletion.
874
+ int64 last_activity_at = 10;
875
+ // The barrier is automatically deleted this many seconds after last_activity_at.
876
+ int64 delete_inactive_after_seconds = 11;
877
+ }
878
+
879
+ // BarrierParticipant is one process's arrival in a given generation (see
880
+ // ListBarrierParticipants).
881
+ message BarrierParticipant {
882
+ string process_id = 1;
883
+ // When the process arrived, Unix nanoseconds.
884
+ int64 arrived_at = 2;
885
+ map<string, string> metadata = 3;
886
+ }