ringo-task-queue 0.1.0.dev0__py3-none-win_amd64.whl → 0.1.0.dev2__py3-none-win_amd64.whl
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.
- ringo_task_queue/_proto/ringo/v1/queue_pb2.py +57 -53
- ringo_task_queue/_proto/ringo/v1/queue_pb2_grpc.py +45 -0
- ringo_task_queue/_version.py +6 -4
- ringo_task_queue/bin/manifest.json +6 -6
- ringo_task_queue/bin/ringo-task-queue-windows-amd64.exe +0 -0
- ringo_task_queue/client.py +49 -15
- ringo_task_queue/worker.py +213 -4
- {ringo_task_queue-0.1.0.dev0.dist-info → ringo_task_queue-0.1.0.dev2.dist-info}/METADATA +60 -6
- ringo_task_queue-0.1.0.dev2.dist-info/RECORD +18 -0
- ringo_task_queue-0.1.0.dev0.dist-info/RECORD +0 -18
- {ringo_task_queue-0.1.0.dev0.dist-info → ringo_task_queue-0.1.0.dev2.dist-info}/WHEEL +0 -0
- {ringo_task_queue-0.1.0.dev0.dist-info → ringo_task_queue-0.1.0.dev2.dist-info}/licenses/LICENSE +0 -0
|
@@ -28,7 +28,7 @@ from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2
|
|
|
28
28
|
from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n,ringo_task_queue/_proto/ringo/v1/queue.proto\x12\x08ringo.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"i\n\x10NegotiateRequest\x12\x10\n\x08sdk_name\x18\x01 \x01(\t\x12\x13\n\x0bsdk_version\x18\x02 \x01(\t\x12\x16\n\x0eprotocol_major\x18\x03 \x01(\r\x12\x16\n\x0eprotocol_minor\x18\x04 \x01(\r\"\x88\x01\n\x11NegotiateResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12\x16\n\x0eprotocol_major\x18\x02 \x01(\r\x12\x16\n\x0eprotocol_minor\x18\x03 \x01(\r\x12\x14\n\x0c\x63\x61pabilities\x18\x04 \x03(\t\x12\x15\n\rsession_token\x18\x05 \x01(\t\"W\n\x0eRequestContext\x12\x16\n\x0eprotocol_major\x18\x01 \x01(\r\x12\x16\n\x0eprotocol_minor\x18\x02 \x01(\r\x12\x15\n\rsession_token\x18\x03 \x01(\t\"\xbd\x01\n\x0b\x45rrorDetail\x12!\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x13.ringo.v1.ErrorCode\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x35\n\x08metadata\x18\x04 \x03(\x0b\x32#.ringo.v1.ErrorDetail.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xed\x01\n\x0bRetryPolicy\x12\x14\n\x0cmax_attempts\x18\x01 \x01(\r\x12)\n\x08strategy\x18\x02 \x01(\x0e\x32\x17.ringo.v1.RetryStrategy\x12\x30\n\rinitial_delay\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12,\n\tmax_delay\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x12\n\nmultiplier\x18\x05 \x01(\x01\x12\x0e\n\x06jitter\x18\x06 \x01(\x01\x12\x19\n\x11\x64\x65\x63rease_priority\x18\x07 \x01(\x08\"\xc6\x01\n\x08TaskSpec\x12\x12\n\nunique_key\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\'\n\x07payload\x18\x03 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x10\n\x08priority\x18\x04 \x01(\x05\x12+\n\x0cretry_policy\x18\x05 \x01(\x0b\x32\x15.ringo.v1.RetryPolicy\x12\x30\n\x0c\x61vailable_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xb8\x04\n\x04Task\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05queue\x18\x02 \x01(\t\x12\x12\n\nunique_key\x18\x03 \x01(\t\x12\x0c\n\x04type\x18\x04 \x01(\t\x12\'\n\x07payload\x18\x05 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x10\n\x08priority\x18\x06 \x01(\x05\x12$\n\x06status\x18\x07 \x01(\x0e\x32\x14.ringo.v1.TaskStatus\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\r\x12\x14\n\x0cmax_attempts\x18\t \x01(\r\x12\x30\n\x0c\x61vailable_at\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\ncreated_at\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0c\x63ompleted_at\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nlast_error\x18\x0e \x01(\t\x12\x1c\n\x14last_error_truncated\x18\x0f \x01(\x08\x12#\n\x08\x61ttempts\x18\x10 \x03(\x0b\x32\x11.ringo.v1.Attempt\x12$\n\x08progress\x18\x11 \x01(\x0b\x32\x12.ringo.v1.Progress\x12*\n\rcurrent_lease\x18\x12 \x01(\x0b\x32\x13.ringo.v1.LeaseInfo\"\xc6\x01\n\x07\x41ttempt\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x11\n\tworker_id\x18\x02 \x01(\t\x12.\n\nstarted_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x66inished_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07outcome\x18\x05 \x01(\t\x12\r\n\x05\x65rror\x18\x06 \x01(\t\x12\x17\n\x0f\x65rror_truncated\x18\x07 \x01(\x08\"k\n\x08Progress\x12\x0f\n\x07\x63urrent\x18\x01 \x01(\x01\x12\r\n\x05total\x18\x02 \x01(\x01\x12\x0f\n\x07message\x18\x03 \x01(\t\x12.\n\nupdated_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"Z\n\tLeaseInfo\x12\x0f\n\x07\x61ttempt\x18\x01 \x01(\r\x12\x11\n\tworker_id\x18\x02 \x01(\t\x12)\n\x05until\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"|\n\x05Lease\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x02 \x01(\r\x12\x13\n\x0blease_token\x18\x03 \x01(\t\x12\x11\n\tworker_id\x18\x04 \x01(\t\x12)\n\x05until\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"J\n\nLeasedTask\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\x12\x1e\n\x05lease\x18\x02 \x01(\x0b\x32\x0f.ringo.v1.Lease\"l\n\x0e\x45nqueueRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12 \n\x04task\x18\x02 \x01(\x0b\x32\x12.ringo.v1.TaskSpec\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"O\n\rEnqueueResult\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x63reated\x18\x02 \x01(\x08\x12\x1c\n\x04task\x18\x03 \x01(\x0b\x32\x0e.ringo.v1.Task\":\n\x0f\x45nqueueResponse\x12\'\n\x06result\x18\x01 \x01(\x0b\x32\x17.ringo.v1.EnqueueResult\"q\n\x12\x45nqueueManyRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12!\n\x05tasks\x18\x02 \x03(\x0b\x32\x12.ringo.v1.TaskSpec\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"o\n\x13\x45nqueueManyResponse\x12(\n\x07results\x18\x01 \x03(\x0b\x32\x17.ringo.v1.EnqueueResult\x12\x15\n\rcreated_count\x18\x02 \x01(\r\x12\x17\n\x0f\x64uplicate_count\x18\x03 \x01(\r\"z\n\x0eGetTaskRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x11\n\x07task_id\x18\x02 \x01(\tH\x00\x12\x14\n\nunique_key\x18\x03 \x01(\tH\x00\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContextB\x05\n\x03key\"/\n\x0fGetTaskResponse\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\"|\n\x10RetryTaskRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x11\n\x07task_id\x18\x02 \x01(\tH\x00\x12\x14\n\nunique_key\x18\x03 \x01(\tH\x00\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContextB\x05\n\x03key\"1\n\x11RetryTaskResponse\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\"\xe2\x01\n\x0c\x43laimRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x11\n\tworker_id\x18\x02 \x01(\t\x12\x12\n\ntask_types\x18\x03 \x03(\t\x12\r\n\x05limit\x18\x04 \x01(\r\x12/\n\x0cwait_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\x0elease_duration\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"4\n\rClaimResponse\x12#\n\x05tasks\x18\x01 \x03(\x0b\x32\x14.ringo.v1.LeasedTask\"A\n\x08LeaseRef\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x02 \x01(\r\x12\x13\n\x0blease_token\x18\x03 \x01(\t\"Z\n\nAckRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"\r\n\x0b\x41\x63kResponse\"\xa3\x01\n\x0bNackRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x37\n\x14retry_delay_override\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\",\n\x0cNackResponse\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\"l\n\rRejectRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\".\n\x0eRejectResponse\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\"\x90\x01\n\x12\x45xtendLeaseRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12,\n\textension\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"5\n\x13\x45xtendLeaseResponse\x12\x1e\n\x05lease\x18\x01 \x01(\x0b\x32\x0f.ringo.v1.Lease\"\x96\x01\n\x15ReportProgressRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12\x0f\n\x07\x63urrent\x18\x02 \x01(\x01\x12\r\n\x05total\x18\x03 \x01(\x01\x12\x0f\n\x07message\x18\x04 \x01(\t\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"\x18\n\x16ReportProgressResponse\"\xc1\x01\n\x12WorkerRegistration\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x11\n\tworker_id\x18\x02 \x01(\t\x12\x12\n\ntask_types\x18\x03 \x03(\t\x12\x17\n\x0fmax_concurrency\x18\x04 \x01(\r\x12\x31\n\x0elease_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"!\n\x0c\x43reditUpdate\x12\x11\n\tavailable\x18\x01 \x01(\r\"\x1c\n\x0bWorkerDrain\x12\r\n\x05\x62\x65gin\x18\x01 \x01(\x08\"q\n\x10WorkerRegistered\x12\x11\n\tworker_id\x18\x01 \x01(\t\x12\x17\n\x0fmax_concurrency\x18\x02 \x01(\r\x12\x31\n\x0elease_duration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\"\x8f\x03\n\x0bWorkRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\x04\x12\x30\n\x08register\x18\x02 \x01(\x0b\x32\x1c.ringo.v1.WorkerRegistrationH\x00\x12(\n\x06\x63redit\x18\x03 \x01(\x0b\x32\x16.ringo.v1.CreditUpdateH\x00\x12#\n\x03\x61\x63k\x18\x04 \x01(\x0b\x32\x14.ringo.v1.AckRequestH\x00\x12%\n\x04nack\x18\x05 \x01(\x0b\x32\x15.ringo.v1.NackRequestH\x00\x12)\n\x06reject\x18\x06 \x01(\x0b\x32\x17.ringo.v1.RejectRequestH\x00\x12\x34\n\x0c\x65xtend_lease\x18\x07 \x01(\x0b\x32\x1c.ringo.v1.ExtendLeaseRequestH\x00\x12\x33\n\x08progress\x18\x08 \x01(\x0b\x32\x1f.ringo.v1.ReportProgressRequestH\x00\x12&\n\x05\x64rain\x18\t \x01(\x0b\x32\x15.ringo.v1.WorkerDrainH\x00\x42\x06\n\x04\x62ody\"F\n\nWorkResult\x12\x12\n\nrequest_id\x18\x01 \x01(\x04\x12$\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x15.ringo.v1.ErrorDetail\"\xc7\x01\n\x0cWorkResponse\x12$\n\x04task\x18\x01 \x01(\x0b\x32\x14.ringo.v1.LeasedTaskH\x00\x12&\n\x06result\x18\x02 \x01(\x0b\x32\x14.ringo.v1.WorkResultH\x00\x12/\n\theartbeat\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00\x12\x30\n\nregistered\x18\x04 \x01(\x0b\x32\x1a.ringo.v1.WorkerRegisteredH\x00\x42\x06\n\x04\x62ody*\xbf\x01\n\nTaskStatus\x12\x1b\n\x17TASK_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15TASK_STATUS_SCHEDULED\x10\x01\x12\x15\n\x11TASK_STATUS_READY\x10\x02\x12\x16\n\x12TASK_STATUS_LEASED\x10\x03\x12\x19\n\x15TASK_STATUS_SUCCEEDED\x10\x04\x12\x14\n\x10TASK_STATUS_DEAD\x10\x05\x12\x19\n\x15TASK_STATUS_CANCELLED\x10\x06*i\n\rRetryStrategy\x12\x1e\n\x1aRETRY_STRATEGY_UNSPECIFIED\x10\x00\x12\x18\n\x14RETRY_STRATEGY_FIXED\x10\x01\x12\x1e\n\x1aRETRY_STRATEGY_EXPONENTIAL\x10\x02*\xac\x02\n\tErrorCode\x12\x1a\n\x16\x45RROR_CODE_UNSPECIFIED\x10\x00\x12\x1f\n\x1b\x45RROR_CODE_INVALID_ARGUMENT\x10\x01\x12\x18\n\x14\x45RROR_CODE_DUPLICATE\x10\x02\x12\x18\n\x14\x45RROR_CODE_NOT_FOUND\x10\x03\x12\x17\n\x13\x45RROR_CODE_CONFLICT\x10\x04\x12\x19\n\x15\x45RROR_CODE_LEASE_LOST\x10\x05\x12\x1a\n\x16\x45RROR_CODE_UNAVAILABLE\x10\x06\x12 \n\x1c\x45RROR_CODE_DEADLINE_EXCEEDED\x10\x07\x12#\n\x1f\x45RROR_CODE_INCOMPATIBLE_VERSION\x10\x08\x12\x17\n\x13\x45RROR_CODE_INTERNAL\x10\t2\xa4\x06\n\x0cQueueService\x12\x44\n\tNegotiate\x12\x1a.ringo.v1.NegotiateRequest\x1a\x1b.ringo.v1.NegotiateResponse\x12>\n\x07\x45nqueue\x12\x18.ringo.v1.EnqueueRequest\x1a\x19.ringo.v1.EnqueueResponse\x12J\n\x0b\x45nqueueMany\x12\x1c.ringo.v1.EnqueueManyRequest\x1a\x1d.ringo.v1.EnqueueManyResponse\x12>\n\x07GetTask\x12\x18.ringo.v1.GetTaskRequest\x1a\x19.ringo.v1.GetTaskResponse\x12\x44\n\tRetryTask\x12\x1a.ringo.v1.RetryTaskRequest\x1a\x1b.ringo.v1.RetryTaskResponse\x12\x38\n\x05\x43laim\x12\x16.ringo.v1.ClaimRequest\x1a\x17.ringo.v1.ClaimResponse\x12\x32\n\x03\x41\x63k\x12\x14.ringo.v1.AckRequest\x1a\x15.ringo.v1.AckResponse\x12\x35\n\x04Nack\x12\x15.ringo.v1.NackRequest\x1a\x16.ringo.v1.NackResponse\x12;\n\x06Reject\x12\x17.ringo.v1.RejectRequest\x1a\x18.ringo.v1.RejectResponse\x12J\n\x0b\x45xtendLease\x12\x1c.ringo.v1.ExtendLeaseRequest\x1a\x1d.ringo.v1.ExtendLeaseResponse\x12S\n\x0eReportProgress\x12\x1f.ringo.v1.ReportProgressRequest\x1a .ringo.v1.ReportProgressResponse\x12\x39\n\x04Work\x12\x15.ringo.v1.WorkRequest\x1a\x16.ringo.v1.WorkResponse(\x01\x30\x01\x42l\n\x16\x64\x65v.ringo.taskqueue.v1B\nQueueProtoP\x01ZDgithub.com/ringo-task-queue/ringo-task-queue/gen/go/ringo/v1;ringov1b\x06proto3')
|
|
31
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n,ringo_task_queue/_proto/ringo/v1/queue.proto\x12\x08ringo.v1\x1a\x1egoogle/protobuf/duration.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"i\n\x10NegotiateRequest\x12\x10\n\x08sdk_name\x18\x01 \x01(\t\x12\x13\n\x0bsdk_version\x18\x02 \x01(\t\x12\x16\n\x0eprotocol_major\x18\x03 \x01(\r\x12\x16\n\x0eprotocol_minor\x18\x04 \x01(\r\"\x88\x01\n\x11NegotiateResponse\x12\x16\n\x0eserver_version\x18\x01 \x01(\t\x12\x16\n\x0eprotocol_major\x18\x02 \x01(\r\x12\x16\n\x0eprotocol_minor\x18\x03 \x01(\r\x12\x14\n\x0c\x63\x61pabilities\x18\x04 \x03(\t\x12\x15\n\rsession_token\x18\x05 \x01(\t\"W\n\x0eRequestContext\x12\x16\n\x0eprotocol_major\x18\x01 \x01(\r\x12\x16\n\x0eprotocol_minor\x18\x02 \x01(\r\x12\x15\n\rsession_token\x18\x03 \x01(\t\"\xbd\x01\n\x0b\x45rrorDetail\x12!\n\x04\x63ode\x18\x01 \x01(\x0e\x32\x13.ringo.v1.ErrorCode\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x12\n\nrequest_id\x18\x03 \x01(\t\x12\x35\n\x08metadata\x18\x04 \x03(\x0b\x32#.ringo.v1.ErrorDetail.MetadataEntry\x1a/\n\rMetadataEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t:\x02\x38\x01\"\xed\x01\n\x0bRetryPolicy\x12\x14\n\x0cmax_attempts\x18\x01 \x01(\r\x12)\n\x08strategy\x18\x02 \x01(\x0e\x32\x17.ringo.v1.RetryStrategy\x12\x30\n\rinitial_delay\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12,\n\tmax_delay\x18\x04 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x12\n\nmultiplier\x18\x05 \x01(\x01\x12\x0e\n\x06jitter\x18\x06 \x01(\x01\x12\x19\n\x11\x64\x65\x63rease_priority\x18\x07 \x01(\x08\"\xc6\x01\n\x08TaskSpec\x12\x12\n\nunique_key\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\'\n\x07payload\x18\x03 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x10\n\x08priority\x18\x04 \x01(\x05\x12+\n\x0cretry_policy\x18\x05 \x01(\x0b\x32\x15.ringo.v1.RetryPolicy\x12\x30\n\x0c\x61vailable_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xb8\x04\n\x04Task\x12\n\n\x02id\x18\x01 \x01(\t\x12\r\n\x05queue\x18\x02 \x01(\t\x12\x12\n\nunique_key\x18\x03 \x01(\t\x12\x0c\n\x04type\x18\x04 \x01(\t\x12\'\n\x07payload\x18\x05 \x01(\x0b\x32\x16.google.protobuf.Value\x12\x10\n\x08priority\x18\x06 \x01(\x05\x12$\n\x06status\x18\x07 \x01(\x0e\x32\x14.ringo.v1.TaskStatus\x12\x0f\n\x07\x61ttempt\x18\x08 \x01(\r\x12\x14\n\x0cmax_attempts\x18\t \x01(\r\x12\x30\n\x0c\x61vailable_at\x18\n \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\ncreated_at\x18\x0b \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x30\n\x0c\x63ompleted_at\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x12\n\nlast_error\x18\x0e \x01(\t\x12\x1c\n\x14last_error_truncated\x18\x0f \x01(\x08\x12#\n\x08\x61ttempts\x18\x10 \x03(\x0b\x32\x11.ringo.v1.Attempt\x12$\n\x08progress\x18\x11 \x01(\x0b\x32\x12.ringo.v1.Progress\x12*\n\rcurrent_lease\x18\x12 \x01(\x0b\x32\x13.ringo.v1.LeaseInfo\"\xc6\x01\n\x07\x41ttempt\x12\x0e\n\x06number\x18\x01 \x01(\r\x12\x11\n\tworker_id\x18\x02 \x01(\t\x12.\n\nstarted_at\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12/\n\x0b\x66inished_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12\x0f\n\x07outcome\x18\x05 \x01(\t\x12\r\n\x05\x65rror\x18\x06 \x01(\t\x12\x17\n\x0f\x65rror_truncated\x18\x07 \x01(\x08\"k\n\x08Progress\x12\x0f\n\x07\x63urrent\x18\x01 \x01(\x01\x12\r\n\x05total\x18\x02 \x01(\x01\x12\x0f\n\x07message\x18\x03 \x01(\t\x12.\n\nupdated_at\x18\x04 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"Z\n\tLeaseInfo\x12\x0f\n\x07\x61ttempt\x18\x01 \x01(\r\x12\x11\n\tworker_id\x18\x02 \x01(\t\x12)\n\x05until\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"|\n\x05Lease\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x02 \x01(\r\x12\x13\n\x0blease_token\x18\x03 \x01(\t\x12\x11\n\tworker_id\x18\x04 \x01(\t\x12)\n\x05until\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"J\n\nLeasedTask\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\x12\x1e\n\x05lease\x18\x02 \x01(\x0b\x32\x0f.ringo.v1.Lease\"l\n\x0e\x45nqueueRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12 \n\x04task\x18\x02 \x01(\x0b\x32\x12.ringo.v1.TaskSpec\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"O\n\rEnqueueResult\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x63reated\x18\x02 \x01(\x08\x12\x1c\n\x04task\x18\x03 \x01(\x0b\x32\x0e.ringo.v1.Task\":\n\x0f\x45nqueueResponse\x12\'\n\x06result\x18\x01 \x01(\x0b\x32\x17.ringo.v1.EnqueueResult\"q\n\x12\x45nqueueManyRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12!\n\x05tasks\x18\x02 \x03(\x0b\x32\x12.ringo.v1.TaskSpec\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"o\n\x13\x45nqueueManyResponse\x12(\n\x07results\x18\x01 \x03(\x0b\x32\x17.ringo.v1.EnqueueResult\x12\x15\n\rcreated_count\x18\x02 \x01(\r\x12\x17\n\x0f\x64uplicate_count\x18\x03 \x01(\r\"z\n\x0eGetTaskRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x11\n\x07task_id\x18\x02 \x01(\tH\x00\x12\x14\n\nunique_key\x18\x03 \x01(\tH\x00\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContextB\x05\n\x03key\"/\n\x0fGetTaskResponse\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\"g\n\x17GetQueueActivityRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x12\n\ntask_types\x18\x02 \x03(\t\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"5\n\x18GetQueueActivityResponse\x12\x19\n\x11\x61\x63tive_task_count\x18\x01 \x01(\x04\"|\n\x10RetryTaskRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x11\n\x07task_id\x18\x02 \x01(\tH\x00\x12\x14\n\nunique_key\x18\x03 \x01(\tH\x00\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContextB\x05\n\x03key\"1\n\x11RetryTaskResponse\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\"\xe2\x01\n\x0c\x43laimRequest\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x11\n\tworker_id\x18\x02 \x01(\t\x12\x12\n\ntask_types\x18\x03 \x03(\t\x12\r\n\x05limit\x18\x04 \x01(\r\x12/\n\x0cwait_timeout\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12\x31\n\x0elease_duration\x18\x06 \x01(\x0b\x32\x19.google.protobuf.Duration\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"4\n\rClaimResponse\x12#\n\x05tasks\x18\x01 \x03(\x0b\x32\x14.ringo.v1.LeasedTask\"A\n\x08LeaseRef\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0f\n\x07\x61ttempt\x18\x02 \x01(\r\x12\x13\n\x0blease_token\x18\x03 \x01(\t\"Z\n\nAckRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"\r\n\x0b\x41\x63kResponse\"\xa3\x01\n\x0bNackRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12\x37\n\x14retry_delay_override\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\",\n\x0cNackResponse\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\"l\n\rRejectRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12\r\n\x05\x65rror\x18\x02 \x01(\t\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\".\n\x0eRejectResponse\x12\x1c\n\x04task\x18\x01 \x01(\x0b\x32\x0e.ringo.v1.Task\"\x90\x01\n\x12\x45xtendLeaseRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12,\n\textension\x18\x02 \x01(\x0b\x32\x19.google.protobuf.Duration\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"5\n\x13\x45xtendLeaseResponse\x12\x1e\n\x05lease\x18\x01 \x01(\x0b\x32\x0f.ringo.v1.Lease\"\x96\x01\n\x15ReportProgressRequest\x12!\n\x05lease\x18\x01 \x01(\x0b\x32\x12.ringo.v1.LeaseRef\x12\x0f\n\x07\x63urrent\x18\x02 \x01(\x01\x12\r\n\x05total\x18\x03 \x01(\x01\x12\x0f\n\x07message\x18\x04 \x01(\t\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"\x18\n\x16ReportProgressResponse\"\xc1\x01\n\x12WorkerRegistration\x12\r\n\x05queue\x18\x01 \x01(\t\x12\x11\n\tworker_id\x18\x02 \x01(\t\x12\x12\n\ntask_types\x18\x03 \x03(\t\x12\x17\n\x0fmax_concurrency\x18\x04 \x01(\r\x12\x31\n\x0elease_duration\x18\x05 \x01(\x0b\x32\x19.google.protobuf.Duration\x12)\n\x07\x63ontext\x18\x0f \x01(\x0b\x32\x18.ringo.v1.RequestContext\"!\n\x0c\x43reditUpdate\x12\x11\n\tavailable\x18\x01 \x01(\r\"\x1c\n\x0bWorkerDrain\x12\r\n\x05\x62\x65gin\x18\x01 \x01(\x08\"q\n\x10WorkerRegistered\x12\x11\n\tworker_id\x18\x01 \x01(\t\x12\x17\n\x0fmax_concurrency\x18\x02 \x01(\r\x12\x31\n\x0elease_duration\x18\x03 \x01(\x0b\x32\x19.google.protobuf.Duration\"\x8f\x03\n\x0bWorkRequest\x12\x12\n\nrequest_id\x18\x01 \x01(\x04\x12\x30\n\x08register\x18\x02 \x01(\x0b\x32\x1c.ringo.v1.WorkerRegistrationH\x00\x12(\n\x06\x63redit\x18\x03 \x01(\x0b\x32\x16.ringo.v1.CreditUpdateH\x00\x12#\n\x03\x61\x63k\x18\x04 \x01(\x0b\x32\x14.ringo.v1.AckRequestH\x00\x12%\n\x04nack\x18\x05 \x01(\x0b\x32\x15.ringo.v1.NackRequestH\x00\x12)\n\x06reject\x18\x06 \x01(\x0b\x32\x17.ringo.v1.RejectRequestH\x00\x12\x34\n\x0c\x65xtend_lease\x18\x07 \x01(\x0b\x32\x1c.ringo.v1.ExtendLeaseRequestH\x00\x12\x33\n\x08progress\x18\x08 \x01(\x0b\x32\x1f.ringo.v1.ReportProgressRequestH\x00\x12&\n\x05\x64rain\x18\t \x01(\x0b\x32\x15.ringo.v1.WorkerDrainH\x00\x42\x06\n\x04\x62ody\"F\n\nWorkResult\x12\x12\n\nrequest_id\x18\x01 \x01(\x04\x12$\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x15.ringo.v1.ErrorDetail\"\xc7\x01\n\x0cWorkResponse\x12$\n\x04task\x18\x01 \x01(\x0b\x32\x14.ringo.v1.LeasedTaskH\x00\x12&\n\x06result\x18\x02 \x01(\x0b\x32\x14.ringo.v1.WorkResultH\x00\x12/\n\theartbeat\x18\x03 \x01(\x0b\x32\x1a.google.protobuf.TimestampH\x00\x12\x30\n\nregistered\x18\x04 \x01(\x0b\x32\x1a.ringo.v1.WorkerRegisteredH\x00\x42\x06\n\x04\x62ody*\xbf\x01\n\nTaskStatus\x12\x1b\n\x17TASK_STATUS_UNSPECIFIED\x10\x00\x12\x19\n\x15TASK_STATUS_SCHEDULED\x10\x01\x12\x15\n\x11TASK_STATUS_READY\x10\x02\x12\x16\n\x12TASK_STATUS_LEASED\x10\x03\x12\x19\n\x15TASK_STATUS_SUCCEEDED\x10\x04\x12\x14\n\x10TASK_STATUS_DEAD\x10\x05\x12\x19\n\x15TASK_STATUS_CANCELLED\x10\x06*i\n\rRetryStrategy\x12\x1e\n\x1aRETRY_STRATEGY_UNSPECIFIED\x10\x00\x12\x18\n\x14RETRY_STRATEGY_FIXED\x10\x01\x12\x1e\n\x1aRETRY_STRATEGY_EXPONENTIAL\x10\x02*\xac\x02\n\tErrorCode\x12\x1a\n\x16\x45RROR_CODE_UNSPECIFIED\x10\x00\x12\x1f\n\x1b\x45RROR_CODE_INVALID_ARGUMENT\x10\x01\x12\x18\n\x14\x45RROR_CODE_DUPLICATE\x10\x02\x12\x18\n\x14\x45RROR_CODE_NOT_FOUND\x10\x03\x12\x17\n\x13\x45RROR_CODE_CONFLICT\x10\x04\x12\x19\n\x15\x45RROR_CODE_LEASE_LOST\x10\x05\x12\x1a\n\x16\x45RROR_CODE_UNAVAILABLE\x10\x06\x12 \n\x1c\x45RROR_CODE_DEADLINE_EXCEEDED\x10\x07\x12#\n\x1f\x45RROR_CODE_INCOMPATIBLE_VERSION\x10\x08\x12\x17\n\x13\x45RROR_CODE_INTERNAL\x10\t2\xff\x06\n\x0cQueueService\x12\x44\n\tNegotiate\x12\x1a.ringo.v1.NegotiateRequest\x1a\x1b.ringo.v1.NegotiateResponse\x12>\n\x07\x45nqueue\x12\x18.ringo.v1.EnqueueRequest\x1a\x19.ringo.v1.EnqueueResponse\x12J\n\x0b\x45nqueueMany\x12\x1c.ringo.v1.EnqueueManyRequest\x1a\x1d.ringo.v1.EnqueueManyResponse\x12>\n\x07GetTask\x12\x18.ringo.v1.GetTaskRequest\x1a\x19.ringo.v1.GetTaskResponse\x12Y\n\x10GetQueueActivity\x12!.ringo.v1.GetQueueActivityRequest\x1a\".ringo.v1.GetQueueActivityResponse\x12\x44\n\tRetryTask\x12\x1a.ringo.v1.RetryTaskRequest\x1a\x1b.ringo.v1.RetryTaskResponse\x12\x38\n\x05\x43laim\x12\x16.ringo.v1.ClaimRequest\x1a\x17.ringo.v1.ClaimResponse\x12\x32\n\x03\x41\x63k\x12\x14.ringo.v1.AckRequest\x1a\x15.ringo.v1.AckResponse\x12\x35\n\x04Nack\x12\x15.ringo.v1.NackRequest\x1a\x16.ringo.v1.NackResponse\x12;\n\x06Reject\x12\x17.ringo.v1.RejectRequest\x1a\x18.ringo.v1.RejectResponse\x12J\n\x0b\x45xtendLease\x12\x1c.ringo.v1.ExtendLeaseRequest\x1a\x1d.ringo.v1.ExtendLeaseResponse\x12S\n\x0eReportProgress\x12\x1f.ringo.v1.ReportProgressRequest\x1a .ringo.v1.ReportProgressResponse\x12\x39\n\x04Work\x12\x15.ringo.v1.WorkRequest\x1a\x16.ringo.v1.WorkResponse(\x01\x30\x01\x42l\n\x16\x64\x65v.ringo.taskqueue.v1B\nQueueProtoP\x01ZDgithub.com/ringo-task-queue/ringo-task-queue/gen/go/ringo/v1;ringov1b\x06proto3')
|
|
32
32
|
|
|
33
33
|
_globals = globals()
|
|
34
34
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -38,12 +38,12 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
|
38
38
|
_globals['DESCRIPTOR']._serialized_options = b'\n\026dev.ringo.taskqueue.v1B\nQueueProtoP\001ZDgithub.com/ringo-task-queue/ringo-task-queue/gen/go/ringo/v1;ringov1'
|
|
39
39
|
_globals['_ERRORDETAIL_METADATAENTRY']._loaded_options = None
|
|
40
40
|
_globals['_ERRORDETAIL_METADATAENTRY']._serialized_options = b'8\001'
|
|
41
|
-
_globals['_TASKSTATUS']._serialized_start=
|
|
42
|
-
_globals['_TASKSTATUS']._serialized_end=
|
|
43
|
-
_globals['_RETRYSTRATEGY']._serialized_start=
|
|
44
|
-
_globals['_RETRYSTRATEGY']._serialized_end=
|
|
45
|
-
_globals['_ERRORCODE']._serialized_start=
|
|
46
|
-
_globals['_ERRORCODE']._serialized_end=
|
|
41
|
+
_globals['_TASKSTATUS']._serialized_start=5546
|
|
42
|
+
_globals['_TASKSTATUS']._serialized_end=5737
|
|
43
|
+
_globals['_RETRYSTRATEGY']._serialized_start=5739
|
|
44
|
+
_globals['_RETRYSTRATEGY']._serialized_end=5844
|
|
45
|
+
_globals['_ERRORCODE']._serialized_start=5847
|
|
46
|
+
_globals['_ERRORCODE']._serialized_end=6147
|
|
47
47
|
_globals['_NEGOTIATEREQUEST']._serialized_start=153
|
|
48
48
|
_globals['_NEGOTIATEREQUEST']._serialized_end=258
|
|
49
49
|
_globals['_NEGOTIATERESPONSE']._serialized_start=261
|
|
@@ -84,50 +84,54 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
|
84
84
|
_globals['_GETTASKREQUEST']._serialized_end=2897
|
|
85
85
|
_globals['_GETTASKRESPONSE']._serialized_start=2899
|
|
86
86
|
_globals['_GETTASKRESPONSE']._serialized_end=2946
|
|
87
|
-
_globals['
|
|
88
|
-
_globals['
|
|
89
|
-
_globals['
|
|
90
|
-
_globals['
|
|
91
|
-
_globals['
|
|
92
|
-
_globals['
|
|
93
|
-
_globals['
|
|
94
|
-
_globals['
|
|
95
|
-
_globals['
|
|
96
|
-
_globals['
|
|
97
|
-
_globals['
|
|
98
|
-
_globals['
|
|
99
|
-
_globals['
|
|
100
|
-
_globals['
|
|
101
|
-
_globals['
|
|
102
|
-
_globals['
|
|
103
|
-
_globals['
|
|
104
|
-
_globals['
|
|
105
|
-
_globals['
|
|
106
|
-
_globals['
|
|
107
|
-
_globals['
|
|
108
|
-
_globals['
|
|
109
|
-
_globals['
|
|
110
|
-
_globals['
|
|
111
|
-
_globals['
|
|
112
|
-
_globals['
|
|
113
|
-
_globals['
|
|
114
|
-
_globals['
|
|
115
|
-
_globals['
|
|
116
|
-
_globals['
|
|
117
|
-
_globals['
|
|
118
|
-
_globals['
|
|
119
|
-
_globals['
|
|
120
|
-
_globals['
|
|
121
|
-
_globals['
|
|
122
|
-
_globals['
|
|
123
|
-
_globals['
|
|
124
|
-
_globals['
|
|
125
|
-
_globals['
|
|
126
|
-
_globals['
|
|
127
|
-
_globals['
|
|
128
|
-
_globals['
|
|
129
|
-
_globals['
|
|
130
|
-
_globals['
|
|
131
|
-
_globals['
|
|
132
|
-
_globals['
|
|
87
|
+
_globals['_GETQUEUEACTIVITYREQUEST']._serialized_start=2948
|
|
88
|
+
_globals['_GETQUEUEACTIVITYREQUEST']._serialized_end=3051
|
|
89
|
+
_globals['_GETQUEUEACTIVITYRESPONSE']._serialized_start=3053
|
|
90
|
+
_globals['_GETQUEUEACTIVITYRESPONSE']._serialized_end=3106
|
|
91
|
+
_globals['_RETRYTASKREQUEST']._serialized_start=3108
|
|
92
|
+
_globals['_RETRYTASKREQUEST']._serialized_end=3232
|
|
93
|
+
_globals['_RETRYTASKRESPONSE']._serialized_start=3234
|
|
94
|
+
_globals['_RETRYTASKRESPONSE']._serialized_end=3283
|
|
95
|
+
_globals['_CLAIMREQUEST']._serialized_start=3286
|
|
96
|
+
_globals['_CLAIMREQUEST']._serialized_end=3512
|
|
97
|
+
_globals['_CLAIMRESPONSE']._serialized_start=3514
|
|
98
|
+
_globals['_CLAIMRESPONSE']._serialized_end=3566
|
|
99
|
+
_globals['_LEASEREF']._serialized_start=3568
|
|
100
|
+
_globals['_LEASEREF']._serialized_end=3633
|
|
101
|
+
_globals['_ACKREQUEST']._serialized_start=3635
|
|
102
|
+
_globals['_ACKREQUEST']._serialized_end=3725
|
|
103
|
+
_globals['_ACKRESPONSE']._serialized_start=3727
|
|
104
|
+
_globals['_ACKRESPONSE']._serialized_end=3740
|
|
105
|
+
_globals['_NACKREQUEST']._serialized_start=3743
|
|
106
|
+
_globals['_NACKREQUEST']._serialized_end=3906
|
|
107
|
+
_globals['_NACKRESPONSE']._serialized_start=3908
|
|
108
|
+
_globals['_NACKRESPONSE']._serialized_end=3952
|
|
109
|
+
_globals['_REJECTREQUEST']._serialized_start=3954
|
|
110
|
+
_globals['_REJECTREQUEST']._serialized_end=4062
|
|
111
|
+
_globals['_REJECTRESPONSE']._serialized_start=4064
|
|
112
|
+
_globals['_REJECTRESPONSE']._serialized_end=4110
|
|
113
|
+
_globals['_EXTENDLEASEREQUEST']._serialized_start=4113
|
|
114
|
+
_globals['_EXTENDLEASEREQUEST']._serialized_end=4257
|
|
115
|
+
_globals['_EXTENDLEASERESPONSE']._serialized_start=4259
|
|
116
|
+
_globals['_EXTENDLEASERESPONSE']._serialized_end=4312
|
|
117
|
+
_globals['_REPORTPROGRESSREQUEST']._serialized_start=4315
|
|
118
|
+
_globals['_REPORTPROGRESSREQUEST']._serialized_end=4465
|
|
119
|
+
_globals['_REPORTPROGRESSRESPONSE']._serialized_start=4467
|
|
120
|
+
_globals['_REPORTPROGRESSRESPONSE']._serialized_end=4491
|
|
121
|
+
_globals['_WORKERREGISTRATION']._serialized_start=4494
|
|
122
|
+
_globals['_WORKERREGISTRATION']._serialized_end=4687
|
|
123
|
+
_globals['_CREDITUPDATE']._serialized_start=4689
|
|
124
|
+
_globals['_CREDITUPDATE']._serialized_end=4722
|
|
125
|
+
_globals['_WORKERDRAIN']._serialized_start=4724
|
|
126
|
+
_globals['_WORKERDRAIN']._serialized_end=4752
|
|
127
|
+
_globals['_WORKERREGISTERED']._serialized_start=4754
|
|
128
|
+
_globals['_WORKERREGISTERED']._serialized_end=4867
|
|
129
|
+
_globals['_WORKREQUEST']._serialized_start=4870
|
|
130
|
+
_globals['_WORKREQUEST']._serialized_end=5269
|
|
131
|
+
_globals['_WORKRESULT']._serialized_start=5271
|
|
132
|
+
_globals['_WORKRESULT']._serialized_end=5341
|
|
133
|
+
_globals['_WORKRESPONSE']._serialized_start=5344
|
|
134
|
+
_globals['_WORKRESPONSE']._serialized_end=5543
|
|
135
|
+
_globals['_QUEUESERVICE']._serialized_start=6150
|
|
136
|
+
_globals['_QUEUESERVICE']._serialized_end=7045
|
|
133
137
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -56,6 +56,11 @@ class QueueServiceStub(object):
|
|
|
56
56
|
request_serializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetTaskRequest.SerializeToString,
|
|
57
57
|
response_deserializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetTaskResponse.FromString,
|
|
58
58
|
_registered_method=True)
|
|
59
|
+
self.GetQueueActivity = channel.unary_unary(
|
|
60
|
+
'/ringo.v1.QueueService/GetQueueActivity',
|
|
61
|
+
request_serializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetQueueActivityRequest.SerializeToString,
|
|
62
|
+
response_deserializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetQueueActivityResponse.FromString,
|
|
63
|
+
_registered_method=True)
|
|
59
64
|
self.RetryTask = channel.unary_unary(
|
|
60
65
|
'/ringo.v1.QueueService/RetryTask',
|
|
61
66
|
request_serializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.RetryTaskRequest.SerializeToString,
|
|
@@ -126,6 +131,14 @@ class QueueServiceServicer(object):
|
|
|
126
131
|
context.set_details('Method not implemented!')
|
|
127
132
|
raise NotImplementedError('Method not implemented!')
|
|
128
133
|
|
|
134
|
+
def GetQueueActivity(self, request, context):
|
|
135
|
+
"""GetQueueActivity returns a point-in-time queue/type-scope activity count.
|
|
136
|
+
It is read-only and does not seal the queue or promise durable completion.
|
|
137
|
+
"""
|
|
138
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
139
|
+
context.set_details('Method not implemented!')
|
|
140
|
+
raise NotImplementedError('Method not implemented!')
|
|
141
|
+
|
|
129
142
|
def RetryTask(self, request, context):
|
|
130
143
|
"""Missing associated documentation comment in .proto file."""
|
|
131
144
|
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
@@ -197,6 +210,11 @@ def add_QueueServiceServicer_to_server(servicer, server):
|
|
|
197
210
|
request_deserializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetTaskRequest.FromString,
|
|
198
211
|
response_serializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetTaskResponse.SerializeToString,
|
|
199
212
|
),
|
|
213
|
+
'GetQueueActivity': grpc.unary_unary_rpc_method_handler(
|
|
214
|
+
servicer.GetQueueActivity,
|
|
215
|
+
request_deserializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetQueueActivityRequest.FromString,
|
|
216
|
+
response_serializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetQueueActivityResponse.SerializeToString,
|
|
217
|
+
),
|
|
200
218
|
'RetryTask': grpc.unary_unary_rpc_method_handler(
|
|
201
219
|
servicer.RetryTask,
|
|
202
220
|
request_deserializer=ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.RetryTaskRequest.FromString,
|
|
@@ -357,6 +375,33 @@ class QueueService(object):
|
|
|
357
375
|
metadata,
|
|
358
376
|
_registered_method=True)
|
|
359
377
|
|
|
378
|
+
@staticmethod
|
|
379
|
+
def GetQueueActivity(request,
|
|
380
|
+
target,
|
|
381
|
+
options=(),
|
|
382
|
+
channel_credentials=None,
|
|
383
|
+
call_credentials=None,
|
|
384
|
+
insecure=False,
|
|
385
|
+
compression=None,
|
|
386
|
+
wait_for_ready=None,
|
|
387
|
+
timeout=None,
|
|
388
|
+
metadata=None):
|
|
389
|
+
return grpc.experimental.unary_unary(
|
|
390
|
+
request,
|
|
391
|
+
target,
|
|
392
|
+
'/ringo.v1.QueueService/GetQueueActivity',
|
|
393
|
+
ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetQueueActivityRequest.SerializeToString,
|
|
394
|
+
ringo__task__queue_dot___proto_dot_ringo_dot_v1_dot_queue__pb2.GetQueueActivityResponse.FromString,
|
|
395
|
+
options,
|
|
396
|
+
channel_credentials,
|
|
397
|
+
insecure,
|
|
398
|
+
call_credentials,
|
|
399
|
+
compression,
|
|
400
|
+
wait_for_ready,
|
|
401
|
+
timeout,
|
|
402
|
+
metadata,
|
|
403
|
+
_registered_method=True)
|
|
404
|
+
|
|
360
405
|
@staticmethod
|
|
361
406
|
def RetryTask(request,
|
|
362
407
|
target,
|
ringo_task_queue/_version.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
"""Release-line constants shared by runtime packaging checks."""
|
|
2
2
|
|
|
3
|
-
SDK_VERSION = "0.1.0.
|
|
3
|
+
SDK_VERSION = "0.1.0.dev2"
|
|
4
4
|
PROTOCOL_MAJOR = 1
|
|
5
|
-
PROTOCOL_MINOR =
|
|
5
|
+
PROTOCOL_MINOR = 1
|
|
6
6
|
SCHEMA_VERSION = 3
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def daemon_version_for_sdk(version: str = SDK_VERSION) -> str:
|
|
10
10
|
"""Map the Python package line to the canonical Go daemon line."""
|
|
11
|
-
if
|
|
12
|
-
|
|
11
|
+
if ".dev" in version:
|
|
12
|
+
base, _, suffix = version.rpartition(".dev")
|
|
13
|
+
if suffix.isdigit():
|
|
14
|
+
return f"{base}-dev"
|
|
13
15
|
return version
|
|
@@ -4,17 +4,17 @@
|
|
|
4
4
|
"arch": "amd64",
|
|
5
5
|
"filename": "ringo-task-queue-windows-amd64.exe",
|
|
6
6
|
"os": "windows",
|
|
7
|
-
"sha256": "
|
|
8
|
-
"size":
|
|
7
|
+
"sha256": "ad38397d8fe70fb4712f43b32d336e6ebb8550a552c9ab376da5f3785686571a",
|
|
8
|
+
"size": 22874624
|
|
9
9
|
}
|
|
10
10
|
],
|
|
11
|
-
"buildCommit": "
|
|
11
|
+
"buildCommit": "38c81fd",
|
|
12
12
|
"buildDate": "2026-03-01T00:00:00Z",
|
|
13
13
|
"manifestVersion": 1,
|
|
14
14
|
"name": "ringo-task-queue",
|
|
15
15
|
"protocolMajor": 1,
|
|
16
|
-
"protocolMinor":
|
|
17
|
-
"releaseManifestSha256": "
|
|
16
|
+
"protocolMinor": 1,
|
|
17
|
+
"releaseManifestSha256": "23e6bb426c34fa417ca0921acfb9d57bbd726616f597894b40cef224fd469eb5",
|
|
18
18
|
"schemaVersion": 3,
|
|
19
|
-
"version": "0.1.0-dev"
|
|
19
|
+
"version": "0.1.0-dev.2"
|
|
20
20
|
}
|
|
Binary file
|
ringo_task_queue/client.py
CHANGED
|
@@ -670,23 +670,36 @@ class TaskQueue:
|
|
|
670
670
|
return EnqueueResult.from_proto(response.result)
|
|
671
671
|
|
|
672
672
|
async def enqueue_many(self, specs: Iterable[TaskSpec]) -> BatchResult:
|
|
673
|
-
"""Enqueue
|
|
673
|
+
"""Enqueue any number of tasks, auto-batching under the server limit.
|
|
674
|
+
|
|
675
|
+
The server enforces a hard limit of ``_MAX_ENQUEUE_BATCH`` (1000)
|
|
676
|
+
tasks per gRPC call. This method transparently splits larger
|
|
677
|
+
iterables into sequential sub-batches, preserving creation order,
|
|
678
|
+
and aggregates the per-item results into a single :class:`BatchResult`.
|
|
679
|
+
|
|
680
|
+
Fail-fast: if any sub-batch fails, the exception propagates and no
|
|
681
|
+
partial result is returned.
|
|
682
|
+
"""
|
|
674
683
|
specs = list(specs)
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
684
|
+
all_results: list[EnqueueResult] = []
|
|
685
|
+
total_created = 0
|
|
686
|
+
total_duplicates = 0
|
|
687
|
+
|
|
688
|
+
for start in range(0, len(specs), _MAX_ENQUEUE_BATCH):
|
|
689
|
+
chunk = specs[start : start + _MAX_ENQUEUE_BATCH]
|
|
690
|
+
request = queue_pb2.EnqueueManyRequest(
|
|
691
|
+
queue=self.name, tasks=[s.to_proto() for s in chunk]
|
|
680
692
|
)
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
693
|
+
request.context.CopyFrom(self._client._require_conn().request_context())
|
|
694
|
+
response = await self._client._require_conn().call("EnqueueMany", request)
|
|
695
|
+
all_results.extend(EnqueueResult.from_proto(r) for r in response.results)
|
|
696
|
+
total_created += response.created_count
|
|
697
|
+
total_duplicates += response.duplicate_count
|
|
698
|
+
|
|
686
699
|
return BatchResult(
|
|
687
|
-
results=
|
|
688
|
-
created_count=
|
|
689
|
-
duplicate_count=
|
|
700
|
+
results=all_results,
|
|
701
|
+
created_count=total_created,
|
|
702
|
+
duplicate_count=total_duplicates,
|
|
690
703
|
)
|
|
691
704
|
|
|
692
705
|
# -- queries ------------------------------------------------------------
|
|
@@ -779,12 +792,32 @@ class TaskQueue:
|
|
|
779
792
|
concurrency: int = 1,
|
|
780
793
|
lease_duration: timedelta = timedelta(seconds=60),
|
|
781
794
|
grace_period: timedelta = timedelta(seconds=30),
|
|
795
|
+
on_idle: Callable[[], Any] | None = None,
|
|
782
796
|
) -> "Worker":
|
|
783
|
-
"""Create a credit-controlled worker over the frozen Work stream.
|
|
797
|
+
"""Create a credit-controlled worker over the frozen Work stream.
|
|
798
|
+
|
|
799
|
+
``on_idle`` is an optional zero-argument callable (sync or awaitable)
|
|
800
|
+
for bounded batch runs: once the worker has registered and sent its
|
|
801
|
+
initial credit, the SDK polls queue activity every 250 ms via the
|
|
802
|
+
read-only ``GetQueueActivity`` RPC scoped to this worker's
|
|
803
|
+
``task_types``; after the activity count has been continuously zero
|
|
804
|
+
for at least 1 s the callback fires exactly once, inline on the
|
|
805
|
+
``run()`` coroutine. A callback that returns normally leaves the
|
|
806
|
+
worker running (and never fires again); any exception it raises —
|
|
807
|
+
including ``SystemExit`` — propagates verbatim out of
|
|
808
|
+
``await worker.run()`` without becoming a task NACK. Workers without
|
|
809
|
+
``on_idle`` never send activity RPCs and stay compatible with
|
|
810
|
+
protocol minor 0 servers; ``on_idle`` requires minor >= 1 and raises
|
|
811
|
+
:class:`IncompatibleVersionError` from ``run()`` otherwise. Never
|
|
812
|
+
call ``worker.close()`` from inside the callback (it would wait on
|
|
813
|
+
the very coroutine executing it).
|
|
814
|
+
"""
|
|
784
815
|
from .worker import Worker
|
|
785
816
|
|
|
786
817
|
if not callable(handler):
|
|
787
818
|
raise InvalidArgumentError("handler must be callable")
|
|
819
|
+
if on_idle is not None and not callable(on_idle):
|
|
820
|
+
raise InvalidArgumentError("on_idle must be callable")
|
|
788
821
|
if concurrency < 1 or concurrency > 2**32 - 1:
|
|
789
822
|
raise InvalidArgumentError("concurrency must fit in a non-zero uint32")
|
|
790
823
|
if lease_duration < timedelta(0):
|
|
@@ -798,6 +831,7 @@ class TaskQueue:
|
|
|
798
831
|
concurrency=concurrency,
|
|
799
832
|
lease_duration=lease_duration,
|
|
800
833
|
grace_period=grace_period,
|
|
834
|
+
on_idle=on_idle,
|
|
801
835
|
)
|
|
802
836
|
self._client._register_worker(worker)
|
|
803
837
|
return worker
|
ringo_task_queue/worker.py
CHANGED
|
@@ -18,19 +18,27 @@ import grpc
|
|
|
18
18
|
from . import _pb
|
|
19
19
|
from ._proto.ringo.v1 import queue_pb2
|
|
20
20
|
from .errors import (
|
|
21
|
+
IncompatibleVersionError,
|
|
21
22
|
LeaseLostError,
|
|
22
23
|
PermanentTaskError,
|
|
23
|
-
RingoError,
|
|
24
24
|
RetryTaskError,
|
|
25
|
+
RingoError,
|
|
25
26
|
UnavailableError,
|
|
26
27
|
error_from_detail,
|
|
27
28
|
map_rpc_error,
|
|
28
29
|
)
|
|
29
30
|
from .models import Task
|
|
30
31
|
|
|
31
|
-
|
|
32
32
|
_MAX_ERROR_BYTES = 256 * 1024
|
|
33
33
|
|
|
34
|
+
#: Fixed on_idle monitor cadence (design §10.6). These are deliberately not
|
|
35
|
+
#: exposed as Worker parameters: the poll interval and the continuous-idle
|
|
36
|
+
#: quiet period are protocol-level constants of the idle-observation feature.
|
|
37
|
+
_IDLE_POLL_SECONDS = 0.25
|
|
38
|
+
_IDLE_QUIET_SECONDS = 1.0
|
|
39
|
+
#: GetQueueActivity was introduced in protocol minor 1.
|
|
40
|
+
_IDLE_MIN_PROTOCOL_MINOR = 1
|
|
41
|
+
|
|
34
42
|
|
|
35
43
|
def _consume_task_exception(task: asyncio.Task[Any]) -> None:
|
|
36
44
|
if not task.cancelled():
|
|
@@ -152,7 +160,8 @@ class Worker:
|
|
|
152
160
|
|
|
153
161
|
``run`` is intentionally a blocking coroutine: it remains active until
|
|
154
162
|
``close`` is called. The client registers workers and drains them before
|
|
155
|
-
closing its channel.
|
|
163
|
+
closing its channel. When ``on_idle`` is configured, ``run`` additionally
|
|
164
|
+
observes queue activity and executes the callback inline at most once.
|
|
156
165
|
"""
|
|
157
166
|
|
|
158
167
|
def __init__(
|
|
@@ -164,6 +173,7 @@ class Worker:
|
|
|
164
173
|
concurrency: int,
|
|
165
174
|
lease_duration: timedelta,
|
|
166
175
|
grace_period: timedelta,
|
|
176
|
+
on_idle: Callable[[], Any] | None = None,
|
|
167
177
|
) -> None:
|
|
168
178
|
if concurrency < 1:
|
|
169
179
|
raise ValueError("concurrency must be >= 1")
|
|
@@ -175,6 +185,21 @@ class Worker:
|
|
|
175
185
|
self._lease_duration = lease_duration
|
|
176
186
|
self._grace_period = max(0.0, grace_period.total_seconds())
|
|
177
187
|
self._worker_id = self._new_worker_id()
|
|
188
|
+
self._on_idle = on_idle
|
|
189
|
+
# on_idle monitor state (design §10.6). ``_idle_candidate`` arms only
|
|
190
|
+
# after WorkerRegistered plus the initial credit of the *current*
|
|
191
|
+
# session; every reset condition disarms it or clears the zero timer.
|
|
192
|
+
self._idle_candidate = False
|
|
193
|
+
self._idle_zero_since: float | None = None
|
|
194
|
+
self._idle_fired = False
|
|
195
|
+
#: Session token captured at WorkerRegistered + initial credit. The
|
|
196
|
+
#: candidate is only observable while the connection still carries
|
|
197
|
+
#: this token: a unary-triggered renegotiation rotates the token
|
|
198
|
+
#: without touching the Work stream and must disarm the monitor.
|
|
199
|
+
self._idle_session_token: str | None = None
|
|
200
|
+
#: Set when the on_idle callback raised: run() must re-raise verbatim
|
|
201
|
+
#: instead of counting it as a Work-stream reconnect failure.
|
|
202
|
+
self._idle_error: BaseException | None = None
|
|
178
203
|
|
|
179
204
|
# close_started means no new stream may be opened, while force_cancel
|
|
180
205
|
# is raised only after the graceful drain window expires. Existing
|
|
@@ -220,14 +245,34 @@ class Worker:
|
|
|
220
245
|
self._run_started = True
|
|
221
246
|
failures = 0
|
|
222
247
|
try:
|
|
248
|
+
if self._on_idle is not None:
|
|
249
|
+
# GetQueueActivity arrived in protocol minor 1; fail fast
|
|
250
|
+
# instead of silently running without idle observation.
|
|
251
|
+
conn = self._client._require_conn()
|
|
252
|
+
if conn._session_minor < _IDLE_MIN_PROTOCOL_MINOR:
|
|
253
|
+
raise IncompatibleVersionError(
|
|
254
|
+
"on_idle requires a server speaking protocol minor"
|
|
255
|
+
f" >= {_IDLE_MIN_PROTOCOL_MINOR}; negotiated minor"
|
|
256
|
+
f" is {conn._session_minor}"
|
|
257
|
+
)
|
|
223
258
|
while not self._close_started.is_set():
|
|
224
259
|
try:
|
|
225
|
-
await self.
|
|
260
|
+
await self._run_session_monitored()
|
|
226
261
|
except asyncio.CancelledError:
|
|
227
262
|
if not self._close_started.is_set():
|
|
228
263
|
raise
|
|
229
264
|
break
|
|
230
265
|
except Exception as exc:
|
|
266
|
+
if self._idle_error is not None:
|
|
267
|
+
# An on_idle callback failure is not a transport
|
|
268
|
+
# error: it must not be retried, reconnected, or
|
|
269
|
+
# converted into a task NACK.
|
|
270
|
+
raise
|
|
271
|
+
if isinstance(exc, IncompatibleVersionError):
|
|
272
|
+
# A reconnect may have renegotiated a protocol
|
|
273
|
+
# downgrade that makes on_idle unservable; surface
|
|
274
|
+
# it instead of burning the reconnect budget.
|
|
275
|
+
raise
|
|
231
276
|
self._stream_error = exc
|
|
232
277
|
failures += 1
|
|
233
278
|
if self._close_started.is_set():
|
|
@@ -259,6 +304,9 @@ class Worker:
|
|
|
259
304
|
async with self._close_lock:
|
|
260
305
|
if self._close_task is None:
|
|
261
306
|
self._close_started.set()
|
|
307
|
+
self._idle_candidate = False
|
|
308
|
+
self._idle_zero_since = None
|
|
309
|
+
self._idle_session_token = None
|
|
262
310
|
self._close_task = asyncio.create_task(
|
|
263
311
|
self._close_impl(), name=f"ringo-close-{self._worker_id}"
|
|
264
312
|
)
|
|
@@ -314,6 +362,10 @@ class Worker:
|
|
|
314
362
|
await asyncio.gather(*tasks, return_exceptions=True)
|
|
315
363
|
|
|
316
364
|
async def _cancel_assignments(self) -> None:
|
|
365
|
+
# Local assignments were reset, so the idle observation restarts too.
|
|
366
|
+
self._idle_candidate = False
|
|
367
|
+
self._idle_zero_since = None
|
|
368
|
+
self._idle_session_token = None
|
|
317
369
|
assignments = list(self._inflight.values())
|
|
318
370
|
self._inflight.clear()
|
|
319
371
|
for assignment in assignments:
|
|
@@ -339,8 +391,156 @@ class Worker:
|
|
|
339
391
|
if assignment.context is not None:
|
|
340
392
|
assignment.context._cancel()
|
|
341
393
|
|
|
394
|
+
async def _run_session_monitored(self) -> None:
|
|
395
|
+
"""Run one Work session, observing queue activity when on_idle is set.
|
|
396
|
+
|
|
397
|
+
Without ``on_idle`` this is exactly ``_run_session()``. With it, the
|
|
398
|
+
poll loop is executed inline by the ``run()`` coroutine itself (never
|
|
399
|
+
in a child task) so a callback exception — including ``SystemExit`` —
|
|
400
|
+
unwinds verbatim through ``await worker.run()``.
|
|
401
|
+
"""
|
|
402
|
+
if self._on_idle is None:
|
|
403
|
+
await self._run_session()
|
|
404
|
+
return
|
|
405
|
+
session_task = asyncio.create_task(
|
|
406
|
+
self._run_session(), name="ringo-worker-session"
|
|
407
|
+
)
|
|
408
|
+
try:
|
|
409
|
+
while True:
|
|
410
|
+
done, _pending = await asyncio.wait(
|
|
411
|
+
(session_task,), timeout=_IDLE_POLL_SECONDS
|
|
412
|
+
)
|
|
413
|
+
if done:
|
|
414
|
+
# Propagate the session outcome (result or stream error).
|
|
415
|
+
return await session_task
|
|
416
|
+
if await self._idle_poll_once():
|
|
417
|
+
# Single-shot fired and returned normally: park on the
|
|
418
|
+
# session instead of waking every poll interval.
|
|
419
|
+
return await session_task
|
|
420
|
+
finally:
|
|
421
|
+
if not session_task.done():
|
|
422
|
+
session_task.cancel()
|
|
423
|
+
await asyncio.gather(session_task, return_exceptions=True)
|
|
424
|
+
|
|
425
|
+
async def _idle_poll_once(self) -> bool:
|
|
426
|
+
"""One read-only, retry-safe activity observation tick.
|
|
427
|
+
|
|
428
|
+
Returns True exactly when the callback fired and returned normally.
|
|
429
|
+
"""
|
|
430
|
+
callback = self._on_idle
|
|
431
|
+
if (
|
|
432
|
+
callback is None
|
|
433
|
+
or self._idle_fired
|
|
434
|
+
or not self._idle_candidate
|
|
435
|
+
or self._close_started.is_set()
|
|
436
|
+
or self._force_cancel.is_set()
|
|
437
|
+
):
|
|
438
|
+
return False
|
|
439
|
+
# Local assignments make the queue non-idle for this worker.
|
|
440
|
+
if self._inflight:
|
|
441
|
+
self._idle_zero_since = None
|
|
442
|
+
return False
|
|
443
|
+
session = self._session_done
|
|
444
|
+
if session is None or session.is_set():
|
|
445
|
+
return False
|
|
446
|
+
# The observation is bound to the token captured at registration: a
|
|
447
|
+
# unary-triggered renegotiation rotates the token without restarting
|
|
448
|
+
# the Work stream. End this session so the run loop re-registers the
|
|
449
|
+
# stream under the fresh token instead of observing a stale session.
|
|
450
|
+
conn = self._client._require_conn()
|
|
451
|
+
if conn._session_token != self._idle_session_token:
|
|
452
|
+
self._end_stale_idle_session(session)
|
|
453
|
+
return False
|
|
454
|
+
request = queue_pb2.GetQueueActivityRequest(
|
|
455
|
+
queue=self._queue.name, task_types=self._task_types
|
|
456
|
+
)
|
|
457
|
+
try:
|
|
458
|
+
response = await conn.call(
|
|
459
|
+
"GetQueueActivity", request, retry_safe=True
|
|
460
|
+
)
|
|
461
|
+
except asyncio.CancelledError:
|
|
462
|
+
raise
|
|
463
|
+
except Exception:
|
|
464
|
+
# A failed observation restarts the quiet window; a later poll
|
|
465
|
+
# may succeed again without tearing the session down.
|
|
466
|
+
self._idle_zero_since = None
|
|
467
|
+
return False
|
|
468
|
+
# The session or its token may have changed while the query was in
|
|
469
|
+
# flight; a stale response must not advance or complete the window.
|
|
470
|
+
if (
|
|
471
|
+
not self._idle_candidate
|
|
472
|
+
or self._session_done is not session
|
|
473
|
+
or session.is_set()
|
|
474
|
+
):
|
|
475
|
+
self._idle_zero_since = None
|
|
476
|
+
return False
|
|
477
|
+
if self._client._require_conn()._session_token != self._idle_session_token:
|
|
478
|
+
self._end_stale_idle_session(session)
|
|
479
|
+
return False
|
|
480
|
+
if response.active_task_count > 0:
|
|
481
|
+
self._idle_zero_since = None
|
|
482
|
+
return False
|
|
483
|
+
now = asyncio.get_running_loop().time()
|
|
484
|
+
if self._idle_zero_since is None:
|
|
485
|
+
self._idle_zero_since = now
|
|
486
|
+
return False
|
|
487
|
+
if now - self._idle_zero_since < _IDLE_QUIET_SECONDS:
|
|
488
|
+
return False
|
|
489
|
+
# Final atomic gate: no await separates these checks from marking
|
|
490
|
+
# fired and invoking the callback, so an assignment landing in a
|
|
491
|
+
# query in-flight window cannot produce a false trigger.
|
|
492
|
+
if (
|
|
493
|
+
self._inflight
|
|
494
|
+
or self._close_started.is_set()
|
|
495
|
+
or self._force_cancel.is_set()
|
|
496
|
+
):
|
|
497
|
+
self._idle_zero_since = None
|
|
498
|
+
return False
|
|
499
|
+
# Single-shot: mark before invoking so the callback can never
|
|
500
|
+
# re-enter the monitor, and so a normal return never fires twice.
|
|
501
|
+
self._idle_fired = True
|
|
502
|
+
try:
|
|
503
|
+
result = callback()
|
|
504
|
+
if inspect.isawaitable(result):
|
|
505
|
+
await result
|
|
506
|
+
except BaseException as exc:
|
|
507
|
+
# Tag callback failures so run() propagates them verbatim
|
|
508
|
+
# instead of feeding them to the reconnect loop.
|
|
509
|
+
self._idle_error = exc
|
|
510
|
+
raise
|
|
511
|
+
return True
|
|
512
|
+
|
|
513
|
+
def _end_stale_idle_session(self, session: asyncio.Event) -> None:
|
|
514
|
+
"""End the current Work session after a token rotation.
|
|
515
|
+
|
|
516
|
+
Setting ``session_done`` is idempotent and is observed as a clean
|
|
517
|
+
stream end: ``_run_session`` returns without a stream error, the run
|
|
518
|
+
loop reconnects, and the next session re-registers (and re-arms the
|
|
519
|
+
idle candidate) under the fresh token. It is neither a callback
|
|
520
|
+
failure nor a reconnect-worthy stream error.
|
|
521
|
+
"""
|
|
522
|
+
self._idle_candidate = False
|
|
523
|
+
self._idle_zero_since = None
|
|
524
|
+
session.set()
|
|
525
|
+
|
|
342
526
|
async def _run_session(self) -> None:
|
|
343
527
|
conn = self._client._require_conn()
|
|
528
|
+
# A new session invalidates any in-flight idle observation.
|
|
529
|
+
self._idle_candidate = False
|
|
530
|
+
self._idle_zero_since = None
|
|
531
|
+
self._idle_session_token = None
|
|
532
|
+
if (
|
|
533
|
+
self._on_idle is not None
|
|
534
|
+
and conn._session_minor < _IDLE_MIN_PROTOCOL_MINOR
|
|
535
|
+
):
|
|
536
|
+
# A reconnect may have renegotiated a downgrade to minor 0.
|
|
537
|
+
# Fail fast before opening the Work stream; run() surfaces this
|
|
538
|
+
# verbatim instead of counting it as a reconnect failure.
|
|
539
|
+
raise IncompatibleVersionError(
|
|
540
|
+
"on_idle requires a server speaking protocol minor"
|
|
541
|
+
f" >= {_IDLE_MIN_PROTOCOL_MINOR}; negotiated minor"
|
|
542
|
+
f" is {conn._session_minor}"
|
|
543
|
+
)
|
|
344
544
|
reg = queue_pb2.WorkerRegistration(
|
|
345
545
|
queue=self._queue.name,
|
|
346
546
|
worker_id=self._worker_id,
|
|
@@ -372,6 +572,15 @@ class Worker:
|
|
|
372
572
|
return
|
|
373
573
|
# Initial credit is sent only after WorkerRegistered was observed.
|
|
374
574
|
await self._send_credit(self._concurrency)
|
|
575
|
+
if self._on_idle is not None and not self._close_started.is_set():
|
|
576
|
+
# Eligible only from the first/current WorkerRegistered plus
|
|
577
|
+
# a successful initial credit of this session. The candidate
|
|
578
|
+
# is bound to the token this stream was registered with: a
|
|
579
|
+
# later unary renegotiation that rotates the token disarms
|
|
580
|
+
# the monitor until the next session.
|
|
581
|
+
self._idle_session_token = reg.context.session_token
|
|
582
|
+
self._idle_candidate = True
|
|
583
|
+
self._idle_zero_since = None
|
|
375
584
|
await self._wait_event_or_session(self._session_done)
|
|
376
585
|
if self._stream_error is not None and not self._close_started.is_set():
|
|
377
586
|
raise self._stream_error
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: ringo-task-queue
|
|
3
|
-
Version: 0.1.0.
|
|
3
|
+
Version: 0.1.0.dev2
|
|
4
4
|
Summary: Python asyncio SDK for Ringo Task Queue with a bundled offline Go daemon
|
|
5
5
|
Author: Ringo Task Queue contributors
|
|
6
6
|
License-Expression: MIT
|
|
@@ -217,7 +217,7 @@ batch = await queue.enqueue_many(
|
|
|
217
217
|
print(batch.created_count, batch.duplicate_count)
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-
|
|
220
|
+
`enqueue_many` 接受任意数量任务,SDK 自动按服务端单批上限 1,000 条切分并顺序发送,最终聚合为单个 `BatchResult`;`batch.results` 保留逐项结果。若任一批次失败,异常直接抛出,不返回部分结果。
|
|
221
221
|
|
|
222
222
|
## 查询和手工重试
|
|
223
223
|
|
|
@@ -234,7 +234,9 @@ reopened = await queue.retry_by_id(result.task_id)
|
|
|
234
234
|
|
|
235
235
|
状态包括 `SCHEDULED`、`READY`、`LEASED`、`SUCCEEDED`、`DEAD` 和 `CANCELLED`。`Task` 还提供 attempt 历史、最后错误、进度和当前 lease 摘要。手工 retry 保留历史和永久去重关系。
|
|
236
236
|
|
|
237
|
-
## Worker
|
|
237
|
+
## Worker(推荐)
|
|
238
|
+
|
|
239
|
+
处理队列任务推荐直接使用 `Worker`,而不是下面的手工 Claim:Worker 自动管理注册、credit、lease 续租、并发和优雅关闭。
|
|
238
240
|
|
|
239
241
|
```python
|
|
240
242
|
from datetime import timedelta
|
|
@@ -260,7 +262,7 @@ worker = queue.worker(
|
|
|
260
262
|
await worker.run()
|
|
261
263
|
```
|
|
262
264
|
|
|
263
|
-
`run()` 一直运行到其他协程调用 `await worker.close()
|
|
265
|
+
`run()` 一直运行到其他协程调用 `await worker.close()`,并且只能调用一次。常驻消费时用 `asyncio.create_task(worker.run())` 启动;已知有限批次(见下)直接 `await worker.run()`。
|
|
264
266
|
|
|
265
267
|
Handler 映射:
|
|
266
268
|
|
|
@@ -276,8 +278,60 @@ Worker 持有 lease token,自动续租并严格控制并发。`TaskContext`
|
|
|
276
278
|
|
|
277
279
|
这是至少一次系统:handler 的外部副作用必须使用 `unique_key` 或任务 ID 实现幂等。
|
|
278
280
|
|
|
281
|
+
### 有限批次与 `on_idle`(PyPI 推荐范式)
|
|
282
|
+
|
|
283
|
+
已知有限批次(例如"把这批 seed 跑完就退出")的推荐写法:**先在 `run()` 之前提交幂等 seed**,再给 Worker 配置一次性的 `on_idle` 回调,并**直接 `await worker.run()`**:
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
import asyncio
|
|
287
|
+
import sys
|
|
288
|
+
|
|
289
|
+
from ringo_task_queue import Ringo
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
async def main() -> None:
|
|
293
|
+
async with Ringo.local("./data/ringo") as client:
|
|
294
|
+
queue = client.queue("email")
|
|
295
|
+
|
|
296
|
+
# 1. 先提交幂等 seed(run() 之前 enqueue)。
|
|
297
|
+
for user_id in (101, 102, 103):
|
|
298
|
+
await queue.enqueue(
|
|
299
|
+
unique_key=f"welcome:{user_id}",
|
|
300
|
+
task_type="send-email",
|
|
301
|
+
payload={"user_id": user_id},
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
async def handle(task, ctx) -> None:
|
|
305
|
+
await send_welcome(task.payload["user_id"])
|
|
306
|
+
|
|
307
|
+
# 2. 队列在该 Worker 的 task type 范围内连续空闲满 1 秒后触发一次。
|
|
308
|
+
worker = queue.worker(
|
|
309
|
+
handle,
|
|
310
|
+
task_types=["send-email"],
|
|
311
|
+
concurrency=4,
|
|
312
|
+
on_idle=lambda: sys.exit(0),
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
# 3. 前台直接 await run();on_idle 触发后整个批次随之结束。
|
|
316
|
+
await worker.run()
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
asyncio.run(main())
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
语义与限制(务必阅读):
|
|
323
|
+
|
|
324
|
+
- **固定参数**:SDK 以 250 ms 间隔轮询、连续空闲满 1 秒触发一次;这两个值是协议级常量,不提供配置参数。
|
|
325
|
+
- **单次触发**:回调最多触发一次。正常返回后 Worker 继续常驻运行且不再触发;要结束进程请在回调里退出(如 `sys.exit(0)`),异常会原样从 `await worker.run()` 传播。
|
|
326
|
+
- **type scope**:活动数只统计该 Worker `task_types` 范围内的任务(`SCHEDULED`/`READY`/`LEASED` 都算活动),不影响队列里其他类型的任务。
|
|
327
|
+
- **开放队列竞态**:空闲观察只是开放队列上的观测快照,不是持久完成判定。回调**正常返回**且 Worker 保持常驻时,观察之后提交的新任务仍会被正常消费;但如果回调直接退出进程(如 `sys.exit(0)`),观测之后、退出之前竞态提交的任务不会被本 Worker 处理,可能留给其他 Worker 或下一次运行。因此 `sys.exit(0)` 范式只适合生产者已经停止的有限批次。需要严格分布式完成判定时,必须另行设计 queue seal/generation。
|
|
328
|
+
- **不要在回调里 `close()`**:`on_idle` 由 `worker.run()` 协程内联执行,在回调里等待同一 Worker/client 的关闭会造成自等待。外层资源作用域(如上面的 `async with`)负责清理。
|
|
329
|
+
- **兼容性**:不带 `on_idle` 的 Worker 从不发送活动查询 RPC,与协议 minor 0 的旧 server 完全兼容;配置 `on_idle` 需要 minor ≥ 1 的 server,旧 server 会在 `run()` 快速抛出 `IncompatibleVersionError`。
|
|
330
|
+
|
|
279
331
|
## 手工 Claim
|
|
280
332
|
|
|
333
|
+
> 常规消费任务优先使用上面推荐的 `Worker`;手工 Claim 适用于需要自行控制 claim/ACK 时序的高级场景。
|
|
334
|
+
|
|
281
335
|
```python
|
|
282
336
|
from datetime import timedelta
|
|
283
337
|
|
|
@@ -367,14 +421,14 @@ except RingoError as exc:
|
|
|
367
421
|
|
|
368
422
|
| 项目 | 默认值或限制 |
|
|
369
423
|
|---|---|
|
|
370
|
-
| 协议 | 1.
|
|
424
|
+
| 协议 | 1.1 |
|
|
371
425
|
| schema | 3 |
|
|
372
426
|
| lease | 60 秒 |
|
|
373
427
|
| worker concurrency | 1 |
|
|
374
428
|
| graceful shutdown | 30 秒 |
|
|
375
429
|
| retry attempts | 默认 3,最大 32 |
|
|
376
430
|
| retry | 指数退避,1 秒到 60 秒,multiplier 2,jitter 0.2 |
|
|
377
|
-
| batch |
|
|
431
|
+
| batch | SDK 自动分批,单批最大 1,000 |
|
|
378
432
|
| payload | 最大 1 MiB UTF-8 JSON |
|
|
379
433
|
| error text | 最大 256 KiB UTF-8 |
|
|
380
434
|
| daemon 自动重启 | 最多 3 次 |
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
ringo_task_queue/__init__.py,sha256=MUeo1atWuaoNITczk6hDs4zYLI18IEpkVBHOE3wGhFc,1381
|
|
2
|
+
ringo_task_queue/_pb.py,sha256=gA8HMCx9ZXEMB-ca6me8CYXdRLLPzUXVIz63Q4bz75I,5683
|
|
3
|
+
ringo_task_queue/_version.py,sha256=ZzMLs6sHjRJhsqQlzaUywRpm7l_Fnt6prJ6UH1e1vAY,446
|
|
4
|
+
ringo_task_queue/binary.py,sha256=lJtFz_t5BuxDV4dMAqQDpP3mhTvJlnPBGnaiB0Z9D04,9526
|
|
5
|
+
ringo_task_queue/client.py,sha256=c7tCI5q2P0EQc_7RZcofHQHewBPVXGwtiLmKk_KUCsI,35380
|
|
6
|
+
ringo_task_queue/daemon.py,sha256=YS8otZpD9hqKeASb2S8ZWLCWzQj6-FYUb-grmYSnrIs,19849
|
|
7
|
+
ringo_task_queue/errors.py,sha256=UCPl1GJSlHzvGPO5WOmkYwLBqZj8Aozlz7sChAXR8pw,4719
|
|
8
|
+
ringo_task_queue/models.py,sha256=MEXh2JKgCbf3vo0EmnjJ_TscwabaW5Yd9i98LSPIrnk,11691
|
|
9
|
+
ringo_task_queue/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
ringo_task_queue/worker.py,sha256=lminZk8MQgOE2Gf6-8cNymaNb4iXpmtLERSaMxgMDqg,40317
|
|
11
|
+
ringo_task_queue/_proto/ringo/v1/queue_pb2.py,sha256=EyddzrHyXbndhxHm_EMlzLXFVMJGQNZEWgV665NM6IQ,18691
|
|
12
|
+
ringo_task_queue/_proto/ringo/v1/queue_pb2_grpc.py,sha256=b_F-9z6npDpHs3VdIJAhYfPKF6e3pJYSQTonripfWLA,28290
|
|
13
|
+
ringo_task_queue/bin/manifest.json,sha256=VXBi2vZJbqz6Cn-nl8Tp0DO402tHIEjwCR5qm-WlNsc,576
|
|
14
|
+
ringo_task_queue/bin/ringo-task-queue-windows-amd64.exe,sha256=rTg5fY_nD7RxL0OzLTNubruFUKVSyas3baXzeFaGVxo,22874624
|
|
15
|
+
ringo_task_queue-0.1.0.dev2.dist-info/METADATA,sha256=jrL95c9BbnhlnFYpq682KHt2DQ76xGF7nCNo1FIxXhY,16957
|
|
16
|
+
ringo_task_queue-0.1.0.dev2.dist-info/WHEEL,sha256=0nQjyt02uAQbhbYKWZzlDb_ZXUmJUwgypQJ-m16yWKo,94
|
|
17
|
+
ringo_task_queue-0.1.0.dev2.dist-info/licenses/LICENSE,sha256=yK3nnJz_bbOAPlcJqAooYcvecNJnBH9miT_X8Qrerv4,1086
|
|
18
|
+
ringo_task_queue-0.1.0.dev2.dist-info/RECORD,,
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
ringo_task_queue/__init__.py,sha256=MUeo1atWuaoNITczk6hDs4zYLI18IEpkVBHOE3wGhFc,1381
|
|
2
|
-
ringo_task_queue/_pb.py,sha256=gA8HMCx9ZXEMB-ca6me8CYXdRLLPzUXVIz63Q4bz75I,5683
|
|
3
|
-
ringo_task_queue/_version.py,sha256=5fU57YlC-4FhzBd2ppLripDFU1qd0QMs-5SWFnFz_9U,388
|
|
4
|
-
ringo_task_queue/binary.py,sha256=lJtFz_t5BuxDV4dMAqQDpP3mhTvJlnPBGnaiB0Z9D04,9526
|
|
5
|
-
ringo_task_queue/client.py,sha256=GT-JiCMshtf_SFUFvjU_ayi7C0JyuQYOeLrmwISoFLc,33570
|
|
6
|
-
ringo_task_queue/daemon.py,sha256=YS8otZpD9hqKeASb2S8ZWLCWzQj6-FYUb-grmYSnrIs,19849
|
|
7
|
-
ringo_task_queue/errors.py,sha256=UCPl1GJSlHzvGPO5WOmkYwLBqZj8Aozlz7sChAXR8pw,4719
|
|
8
|
-
ringo_task_queue/models.py,sha256=MEXh2JKgCbf3vo0EmnjJ_TscwabaW5Yd9i98LSPIrnk,11691
|
|
9
|
-
ringo_task_queue/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
-
ringo_task_queue/worker.py,sha256=LD-J9XnQBxJWC2xvVi4tCAzms-O7wfkflSnoEFZXwnM,30366
|
|
11
|
-
ringo_task_queue/_proto/ringo/v1/queue_pb2.py,sha256=Z4S0mNwPerMshRr7DUooj9oeecbaYG4JUpMJJlwVb0o,18074
|
|
12
|
-
ringo_task_queue/_proto/ringo/v1/queue_pb2_grpc.py,sha256=eKtdXhZk3BP1I9IaYQlEgUF_K2WZLzBuIq7koWLhQ00,26066
|
|
13
|
-
ringo_task_queue/bin/manifest.json,sha256=6mfoRB8VFN4NAX1NVfYHx4IJmmImAV1eBgJZhK9UrFY,572
|
|
14
|
-
ringo_task_queue/bin/ringo-task-queue-windows-amd64.exe,sha256=t5i_fAW3fq0GIjOSpiDY5M246bMYfviVHnZPhDHL5N8,22699520
|
|
15
|
-
ringo_task_queue-0.1.0.dev0.dist-info/METADATA,sha256=s_SkJVKmqC2OqhdIDGGKlu0hZvPWqFypqbhtdT5iF7A,13515
|
|
16
|
-
ringo_task_queue-0.1.0.dev0.dist-info/WHEEL,sha256=0nQjyt02uAQbhbYKWZzlDb_ZXUmJUwgypQJ-m16yWKo,94
|
|
17
|
-
ringo_task_queue-0.1.0.dev0.dist-info/licenses/LICENSE,sha256=yK3nnJz_bbOAPlcJqAooYcvecNJnBH9miT_X8Qrerv4,1086
|
|
18
|
-
ringo_task_queue-0.1.0.dev0.dist-info/RECORD,,
|
|
File without changes
|
{ringo_task_queue-0.1.0.dev0.dist-info → ringo_task_queue-0.1.0.dev2.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|