Feat: Durable Memoization (#3112)

* feat: initial engine / db work

* chore: gen python

* feat: initial python work

* feat: wiring

* feat: initial test

* fix: scope memo key to the run id (we might not even need this)

* chore: gen, docstring

* fix: mandatory result type

* fix: docs

* fix: log a warning and don't cache

* fix: add test for non-unique keys, fix some bugs

* chore: lint

* chore: naming

* fix: more naming

* fix: comment

* chore: gen

* fix: docs

* fix: naming, ugh

* chore: gen

* chore: gen

* fix: always send event log entry and get ack

* fix: initial rework of memo to only use stream

* fix: start reworking python side

* fix: finish wiring up memo put

* chore: fmt

* chore: comment for monday

* fix: start reworking signature

* fix: docstring

* fix: union type for send event to improve typing a bunch

* fix: memo key

* chore: gen

* fix: rm unused query

* fix: comments
This commit is contained in:
matt
2026-03-01 16:27:56 -08:00
committed by GitHub
parent e2eb3f05e9
commit 77f769bd66
16 changed files with 998 additions and 378 deletions
+19
View File
@@ -40,10 +40,15 @@ message DurableTaskEventRequest {
string durable_task_external_id = 2;
DurableTaskEventKind kind = 3;
optional bytes payload = 4;
// Fields for DURABLE_TASK_TRIGGER_KIND_WAIT_FOR
optional DurableEventListenerConditions wait_for_conditions = 5;
// Fields for DURABLE_TASK_TRIGGER_KIND_RUN (spawning child workflows)
optional TriggerWorkflowRequest trigger_opts = 6;
// Fields for DURABLE_TASK_TRIGGER_KIND_MEMO
optional bytes memo_key = 7;
}
message DurableTaskEventAckResponse {
@@ -51,6 +56,10 @@ message DurableTaskEventAckResponse {
string durable_task_external_id = 2;
int64 branch_id = 3;
int64 node_id = 4;
// memo fields
bool memo_already_existed = 5;
optional bytes memo_result_payload = 6;
}
message DurableTaskEventLogEntryCompletedResponse {
@@ -85,12 +94,22 @@ message DurableTaskWorkerStatusRequest {
}
message DurableTaskCompleteMemoRequest {
string durable_task_external_id = 1;
int32 invocation_count = 2;
int64 branch_id = 3;
int64 node_id = 4;
bytes payload = 5;
bytes memo_key = 6;
}
message DurableTaskRequest {
oneof message {
DurableTaskRequestRegisterWorker register_worker = 1;
DurableTaskEventRequest event = 2;
DurableTaskEvictInvocationRequest evict_invocation = 3;
DurableTaskWorkerStatusRequest worker_status = 4;
DurableTaskCompleteMemoRequest complete_memo = 5;
}
}
+27
View File
@@ -275,6 +275,33 @@ async def durable_replay_reset(
)
class SleepResult(BaseModel):
message: str
duration: float
class MemoInput(BaseModel):
message: str
async def expensive_computation(message: str) -> SleepResult:
await asyncio.sleep(SLEEP_TIME)
return SleepResult(message=message, duration=SLEEP_TIME)
@hatchet.durable_task(input_validator=MemoInput)
async def memo_task(input: MemoInput, ctx: DurableContext) -> SleepResult:
start = time.time()
res = await ctx.aio_memo(
expensive_computation,
SleepResult,
input.message,
)
return SleepResult(message=res.message, duration=time.time() - start)
def main() -> None:
worker = hatchet.worker(
"durable-worker",
+2
View File
@@ -41,6 +41,7 @@ from examples.durable.worker import (
durable_spawn_dag,
durable_non_determinism,
durable_replay_reset,
memo_task,
)
from examples.durable_eviction.worker import (
child_task as eviction_child_task,
@@ -135,6 +136,7 @@ def main() -> None:
dag_child_workflow,
durable_non_determinism,
durable_replay_reset,
memo_task,
evictable_sleep,
evictable_wait_for_event,
evictable_child_spawn,
+40 -6
View File
@@ -412,6 +412,9 @@ func (d *DispatcherServiceImpl) handleDurableTaskRequest(
case *contracts.DurableTaskRequest_WorkerStatus:
return d.handleWorkerStatus(ctx, invocation, msg.WorkerStatus)
case *contracts.DurableTaskRequest_CompleteMemo:
return d.handleCompleteMemo(ctx, invocation, msg.CompleteMemo)
default:
return status.Errorf(codes.InvalidArgument, "unknown message type: %T", msg)
}
@@ -542,6 +545,7 @@ func (d *DispatcherServiceImpl) handleDurableTaskEvent(
WaitForConditions: createConditionOpts,
InvocationCount: req.InvocationCount,
TriggerOpts: triggerOpts,
MemoKey: req.MemoKey,
})
var nde *v1.NonDeterminismError
@@ -574,14 +578,18 @@ func (d *DispatcherServiceImpl) handleDurableTaskEvent(
}
}
ackResp := &contracts.DurableTaskEventAckResponse{
InvocationCount: req.InvocationCount,
DurableTaskExternalId: req.DurableTaskExternalId,
NodeId: ingestionResult.NodeId,
BranchId: ingestionResult.BranchId,
MemoAlreadyExisted: ingestionResult.AlreadyExisted,
MemoResultPayload: ingestionResult.ResultPayload,
}
err = invocation.send(&contracts.DurableTaskResponse{
Message: &contracts.DurableTaskResponse_TriggerAck{
TriggerAck: &contracts.DurableTaskEventAckResponse{
InvocationCount: req.InvocationCount,
DurableTaskExternalId: req.DurableTaskExternalId,
NodeId: ingestionResult.NodeId,
BranchId: ingestionResult.BranchId,
},
TriggerAck: ackResp,
},
})
@@ -607,6 +615,32 @@ func (d *DispatcherServiceImpl) handleDurableTaskEvent(
return nil
}
func (d *DispatcherServiceImpl) handleCompleteMemo(
ctx context.Context,
invocation *durableTaskInvocation,
req *contracts.DurableTaskCompleteMemoRequest,
) error {
taskExternalId, err := uuid.Parse(req.DurableTaskExternalId)
if err != nil {
return status.Errorf(codes.InvalidArgument, "invalid durable_task_external_id: %v", err)
}
err = d.repo.DurableEvents().CompleteMemoEntry(ctx, v1.CompleteMemoEntryOpts{
TenantId: invocation.tenantId,
TaskExternalId: taskExternalId,
InvocationCount: req.InvocationCount,
BranchId: req.BranchId,
NodeId: req.NodeId,
MemoKey: req.MemoKey,
Payload: req.Payload,
})
if err != nil {
return status.Errorf(codes.Internal, "failed to complete memo entry: %v", err)
}
return nil
}
func (d *DispatcherServiceImpl) sendEvictionError(invocation *durableTaskInvocation, req *contracts.DurableTaskEvictInvocationRequest, errMsg string) error {
return invocation.send(&contracts.DurableTaskResponse{
Message: &contracts.DurableTaskResponse_Error{
+428 -253
View File
@@ -222,13 +222,16 @@ type DurableTaskEventRequest struct {
// incremented by one since the previous invocation. This allows the server (and the worker) to have a way of
// differentiating between different attempts of the same task running in different places, to prevent race conditions
// and other problems from duplication. It also allows for older invocations to be evicted cleanly
InvocationCount int32 `protobuf:"varint,1,opt,name=invocation_count,json=invocationCount,proto3" json:"invocation_count,omitempty"`
DurableTaskExternalId string `protobuf:"bytes,2,opt,name=durable_task_external_id,json=durableTaskExternalId,proto3" json:"durable_task_external_id,omitempty"`
Kind DurableTaskEventKind `protobuf:"varint,3,opt,name=kind,proto3,enum=v1.DurableTaskEventKind" json:"kind,omitempty"`
Payload []byte `protobuf:"bytes,4,opt,name=payload,proto3,oneof" json:"payload,omitempty"`
WaitForConditions *DurableEventListenerConditions `protobuf:"bytes,5,opt,name=wait_for_conditions,json=waitForConditions,proto3,oneof" json:"wait_for_conditions,omitempty"`
InvocationCount int32 `protobuf:"varint,1,opt,name=invocation_count,json=invocationCount,proto3" json:"invocation_count,omitempty"`
DurableTaskExternalId string `protobuf:"bytes,2,opt,name=durable_task_external_id,json=durableTaskExternalId,proto3" json:"durable_task_external_id,omitempty"`
Kind DurableTaskEventKind `protobuf:"varint,3,opt,name=kind,proto3,enum=v1.DurableTaskEventKind" json:"kind,omitempty"`
Payload []byte `protobuf:"bytes,4,opt,name=payload,proto3,oneof" json:"payload,omitempty"`
// Fields for DURABLE_TASK_TRIGGER_KIND_WAIT_FOR
WaitForConditions *DurableEventListenerConditions `protobuf:"bytes,5,opt,name=wait_for_conditions,json=waitForConditions,proto3,oneof" json:"wait_for_conditions,omitempty"`
// Fields for DURABLE_TASK_TRIGGER_KIND_RUN (spawning child workflows)
TriggerOpts *TriggerWorkflowRequest `protobuf:"bytes,6,opt,name=trigger_opts,json=triggerOpts,proto3,oneof" json:"trigger_opts,omitempty"`
// Fields for DURABLE_TASK_TRIGGER_KIND_MEMO
MemoKey []byte `protobuf:"bytes,7,opt,name=memo_key,json=memoKey,proto3,oneof" json:"memo_key,omitempty"`
}
func (x *DurableTaskEventRequest) Reset() {
@@ -305,6 +308,13 @@ func (x *DurableTaskEventRequest) GetTriggerOpts() *TriggerWorkflowRequest {
return nil
}
func (x *DurableTaskEventRequest) GetMemoKey() []byte {
if x != nil {
return x.MemoKey
}
return nil
}
type DurableTaskEventAckResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -314,6 +324,9 @@ type DurableTaskEventAckResponse struct {
DurableTaskExternalId string `protobuf:"bytes,2,opt,name=durable_task_external_id,json=durableTaskExternalId,proto3" json:"durable_task_external_id,omitempty"`
BranchId int64 `protobuf:"varint,3,opt,name=branch_id,json=branchId,proto3" json:"branch_id,omitempty"`
NodeId int64 `protobuf:"varint,4,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
// memo fields
MemoAlreadyExisted bool `protobuf:"varint,5,opt,name=memo_already_existed,json=memoAlreadyExisted,proto3" json:"memo_already_existed,omitempty"`
MemoResultPayload []byte `protobuf:"bytes,6,opt,name=memo_result_payload,json=memoResultPayload,proto3,oneof" json:"memo_result_payload,omitempty"`
}
func (x *DurableTaskEventAckResponse) Reset() {
@@ -376,6 +389,20 @@ func (x *DurableTaskEventAckResponse) GetNodeId() int64 {
return 0
}
func (x *DurableTaskEventAckResponse) GetMemoAlreadyExisted() bool {
if x != nil {
return x.MemoAlreadyExisted
}
return false
}
func (x *DurableTaskEventAckResponse) GetMemoResultPayload() []byte {
if x != nil {
return x.MemoResultPayload
}
return nil
}
type DurableTaskEventLogEntryCompletedResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -692,6 +719,93 @@ func (x *DurableTaskWorkerStatusRequest) GetWaitingEntries() []*DurableTaskAwait
return nil
}
type DurableTaskCompleteMemoRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
DurableTaskExternalId string `protobuf:"bytes,1,opt,name=durable_task_external_id,json=durableTaskExternalId,proto3" json:"durable_task_external_id,omitempty"`
InvocationCount int32 `protobuf:"varint,2,opt,name=invocation_count,json=invocationCount,proto3" json:"invocation_count,omitempty"`
BranchId int64 `protobuf:"varint,3,opt,name=branch_id,json=branchId,proto3" json:"branch_id,omitempty"`
NodeId int64 `protobuf:"varint,4,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
Payload []byte `protobuf:"bytes,5,opt,name=payload,proto3" json:"payload,omitempty"`
MemoKey []byte `protobuf:"bytes,6,opt,name=memo_key,json=memoKey,proto3" json:"memo_key,omitempty"`
}
func (x *DurableTaskCompleteMemoRequest) Reset() {
*x = DurableTaskCompleteMemoRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_dispatcher_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DurableTaskCompleteMemoRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DurableTaskCompleteMemoRequest) ProtoMessage() {}
func (x *DurableTaskCompleteMemoRequest) ProtoReflect() protoreflect.Message {
mi := &file_v1_dispatcher_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DurableTaskCompleteMemoRequest.ProtoReflect.Descriptor instead.
func (*DurableTaskCompleteMemoRequest) Descriptor() ([]byte, []int) {
return file_v1_dispatcher_proto_rawDescGZIP(), []int{9}
}
func (x *DurableTaskCompleteMemoRequest) GetDurableTaskExternalId() string {
if x != nil {
return x.DurableTaskExternalId
}
return ""
}
func (x *DurableTaskCompleteMemoRequest) GetInvocationCount() int32 {
if x != nil {
return x.InvocationCount
}
return 0
}
func (x *DurableTaskCompleteMemoRequest) GetBranchId() int64 {
if x != nil {
return x.BranchId
}
return 0
}
func (x *DurableTaskCompleteMemoRequest) GetNodeId() int64 {
if x != nil {
return x.NodeId
}
return 0
}
func (x *DurableTaskCompleteMemoRequest) GetPayload() []byte {
if x != nil {
return x.Payload
}
return nil
}
func (x *DurableTaskCompleteMemoRequest) GetMemoKey() []byte {
if x != nil {
return x.MemoKey
}
return nil
}
type DurableTaskRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -703,13 +817,14 @@ type DurableTaskRequest struct {
// *DurableTaskRequest_Event
// *DurableTaskRequest_EvictInvocation
// *DurableTaskRequest_WorkerStatus
// *DurableTaskRequest_CompleteMemo
Message isDurableTaskRequest_Message `protobuf_oneof:"message"`
}
func (x *DurableTaskRequest) Reset() {
*x = DurableTaskRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_dispatcher_proto_msgTypes[9]
mi := &file_v1_dispatcher_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -722,7 +837,7 @@ func (x *DurableTaskRequest) String() string {
func (*DurableTaskRequest) ProtoMessage() {}
func (x *DurableTaskRequest) ProtoReflect() protoreflect.Message {
mi := &file_v1_dispatcher_proto_msgTypes[9]
mi := &file_v1_dispatcher_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -735,7 +850,7 @@ func (x *DurableTaskRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DurableTaskRequest.ProtoReflect.Descriptor instead.
func (*DurableTaskRequest) Descriptor() ([]byte, []int) {
return file_v1_dispatcher_proto_rawDescGZIP(), []int{9}
return file_v1_dispatcher_proto_rawDescGZIP(), []int{10}
}
func (m *DurableTaskRequest) GetMessage() isDurableTaskRequest_Message {
@@ -773,6 +888,13 @@ func (x *DurableTaskRequest) GetWorkerStatus() *DurableTaskWorkerStatusRequest {
return nil
}
func (x *DurableTaskRequest) GetCompleteMemo() *DurableTaskCompleteMemoRequest {
if x, ok := x.GetMessage().(*DurableTaskRequest_CompleteMemo); ok {
return x.CompleteMemo
}
return nil
}
type isDurableTaskRequest_Message interface {
isDurableTaskRequest_Message()
}
@@ -793,6 +915,10 @@ type DurableTaskRequest_WorkerStatus struct {
WorkerStatus *DurableTaskWorkerStatusRequest `protobuf:"bytes,4,opt,name=worker_status,json=workerStatus,proto3,oneof"`
}
type DurableTaskRequest_CompleteMemo struct {
CompleteMemo *DurableTaskCompleteMemoRequest `protobuf:"bytes,5,opt,name=complete_memo,json=completeMemo,proto3,oneof"`
}
func (*DurableTaskRequest_RegisterWorker) isDurableTaskRequest_Message() {}
func (*DurableTaskRequest_Event) isDurableTaskRequest_Message() {}
@@ -801,6 +927,8 @@ func (*DurableTaskRequest_EvictInvocation) isDurableTaskRequest_Message() {}
func (*DurableTaskRequest_WorkerStatus) isDurableTaskRequest_Message() {}
func (*DurableTaskRequest_CompleteMemo) isDurableTaskRequest_Message() {}
type DurableTaskErrorResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -817,7 +945,7 @@ type DurableTaskErrorResponse struct {
func (x *DurableTaskErrorResponse) Reset() {
*x = DurableTaskErrorResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_dispatcher_proto_msgTypes[10]
mi := &file_v1_dispatcher_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -830,7 +958,7 @@ func (x *DurableTaskErrorResponse) String() string {
func (*DurableTaskErrorResponse) ProtoMessage() {}
func (x *DurableTaskErrorResponse) ProtoReflect() protoreflect.Message {
mi := &file_v1_dispatcher_proto_msgTypes[10]
mi := &file_v1_dispatcher_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -843,7 +971,7 @@ func (x *DurableTaskErrorResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DurableTaskErrorResponse.ProtoReflect.Descriptor instead.
func (*DurableTaskErrorResponse) Descriptor() ([]byte, []int) {
return file_v1_dispatcher_proto_rawDescGZIP(), []int{10}
return file_v1_dispatcher_proto_rawDescGZIP(), []int{11}
}
func (x *DurableTaskErrorResponse) GetDurableTaskExternalId() string {
@@ -906,7 +1034,7 @@ type DurableTaskResponse struct {
func (x *DurableTaskResponse) Reset() {
*x = DurableTaskResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_dispatcher_proto_msgTypes[11]
mi := &file_v1_dispatcher_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -919,7 +1047,7 @@ func (x *DurableTaskResponse) String() string {
func (*DurableTaskResponse) ProtoMessage() {}
func (x *DurableTaskResponse) ProtoReflect() protoreflect.Message {
mi := &file_v1_dispatcher_proto_msgTypes[11]
mi := &file_v1_dispatcher_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -932,7 +1060,7 @@ func (x *DurableTaskResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DurableTaskResponse.ProtoReflect.Descriptor instead.
func (*DurableTaskResponse) Descriptor() ([]byte, []int) {
return file_v1_dispatcher_proto_rawDescGZIP(), []int{11}
return file_v1_dispatcher_proto_rawDescGZIP(), []int{12}
}
func (m *DurableTaskResponse) GetMessage() isDurableTaskResponse_Message {
@@ -1024,7 +1152,7 @@ type RegisterDurableEventRequest struct {
func (x *RegisterDurableEventRequest) Reset() {
*x = RegisterDurableEventRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_dispatcher_proto_msgTypes[12]
mi := &file_v1_dispatcher_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1037,7 +1165,7 @@ func (x *RegisterDurableEventRequest) String() string {
func (*RegisterDurableEventRequest) ProtoMessage() {}
func (x *RegisterDurableEventRequest) ProtoReflect() protoreflect.Message {
mi := &file_v1_dispatcher_proto_msgTypes[12]
mi := &file_v1_dispatcher_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1050,7 +1178,7 @@ func (x *RegisterDurableEventRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use RegisterDurableEventRequest.ProtoReflect.Descriptor instead.
func (*RegisterDurableEventRequest) Descriptor() ([]byte, []int) {
return file_v1_dispatcher_proto_rawDescGZIP(), []int{12}
return file_v1_dispatcher_proto_rawDescGZIP(), []int{13}
}
func (x *RegisterDurableEventRequest) GetTaskId() string {
@@ -1083,7 +1211,7 @@ type RegisterDurableEventResponse struct {
func (x *RegisterDurableEventResponse) Reset() {
*x = RegisterDurableEventResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_dispatcher_proto_msgTypes[13]
mi := &file_v1_dispatcher_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1096,7 +1224,7 @@ func (x *RegisterDurableEventResponse) String() string {
func (*RegisterDurableEventResponse) ProtoMessage() {}
func (x *RegisterDurableEventResponse) ProtoReflect() protoreflect.Message {
mi := &file_v1_dispatcher_proto_msgTypes[13]
mi := &file_v1_dispatcher_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1109,7 +1237,7 @@ func (x *RegisterDurableEventResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use RegisterDurableEventResponse.ProtoReflect.Descriptor instead.
func (*RegisterDurableEventResponse) Descriptor() ([]byte, []int) {
return file_v1_dispatcher_proto_rawDescGZIP(), []int{13}
return file_v1_dispatcher_proto_rawDescGZIP(), []int{14}
}
type ListenForDurableEventRequest struct {
@@ -1124,7 +1252,7 @@ type ListenForDurableEventRequest struct {
func (x *ListenForDurableEventRequest) Reset() {
*x = ListenForDurableEventRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_dispatcher_proto_msgTypes[14]
mi := &file_v1_dispatcher_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1137,7 +1265,7 @@ func (x *ListenForDurableEventRequest) String() string {
func (*ListenForDurableEventRequest) ProtoMessage() {}
func (x *ListenForDurableEventRequest) ProtoReflect() protoreflect.Message {
mi := &file_v1_dispatcher_proto_msgTypes[14]
mi := &file_v1_dispatcher_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1150,7 +1278,7 @@ func (x *ListenForDurableEventRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use ListenForDurableEventRequest.ProtoReflect.Descriptor instead.
func (*ListenForDurableEventRequest) Descriptor() ([]byte, []int) {
return file_v1_dispatcher_proto_rawDescGZIP(), []int{14}
return file_v1_dispatcher_proto_rawDescGZIP(), []int{15}
}
func (x *ListenForDurableEventRequest) GetTaskId() string {
@@ -1180,7 +1308,7 @@ type DurableEvent struct {
func (x *DurableEvent) Reset() {
*x = DurableEvent{}
if protoimpl.UnsafeEnabled {
mi := &file_v1_dispatcher_proto_msgTypes[15]
mi := &file_v1_dispatcher_proto_msgTypes[16]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1193,7 +1321,7 @@ func (x *DurableEvent) String() string {
func (*DurableEvent) ProtoMessage() {}
func (x *DurableEvent) ProtoReflect() protoreflect.Message {
mi := &file_v1_dispatcher_proto_msgTypes[15]
mi := &file_v1_dispatcher_proto_msgTypes[16]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1206,7 +1334,7 @@ func (x *DurableEvent) ProtoReflect() protoreflect.Message {
// Deprecated: Use DurableEvent.ProtoReflect.Descriptor instead.
func (*DurableEvent) Descriptor() ([]byte, []int) {
return file_v1_dispatcher_proto_rawDescGZIP(), []int{15}
return file_v1_dispatcher_proto_rawDescGZIP(), []int{16}
}
func (x *DurableEvent) GetTaskId() string {
@@ -1246,7 +1374,7 @@ var file_v1_dispatcher_proto_rawDesc = []byte{
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x57, 0x6f, 0x72,
0x6b, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64,
0x22, 0x9c, 0x03, 0x0a, 0x17, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b,
0x22, 0xc9, 0x03, 0x0a, 0x17, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b,
0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10,
0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69,
@@ -1268,199 +1396,230 @@ var file_v1_dispatcher_proto_rawDesc = []byte{
0x72, 0x5f, 0x6f, 0x70, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x76,
0x31, 0x2e, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f,
0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x02, 0x52, 0x0b, 0x74, 0x72, 0x69, 0x67,
0x67, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x73, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70,
0x67, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x73, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x6d, 0x65,
0x6d, 0x6f, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x03, 0x52, 0x07,
0x6d, 0x65, 0x6d, 0x6f, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x70,
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x16, 0x0a, 0x14, 0x5f, 0x77, 0x61, 0x69, 0x74, 0x5f,
0x66, 0x6f, 0x72, 0x5f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0f,
0x0a, 0x0d, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x74, 0x73, 0x22,
0xb7, 0x01, 0x0a, 0x1b, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45,
0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75,
0x72, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75,
0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x64,
0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x64,
0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28,
0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0xdf, 0x01, 0x0a, 0x29, 0x44, 0x75,
0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x6f,
0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72, 0x61, 0x62,
0x0a, 0x0d, 0x5f, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x74, 0x73, 0x42,
0x0b, 0x0a, 0x09, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x6b, 0x65, 0x79, 0x22, 0xb6, 0x02, 0x0a,
0x1b, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e,
0x74, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10,
0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72, 0x61, 0x62,
0x6c, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72, 0x61, 0x62,
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72, 0x61, 0x62,
0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64,
0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08,
0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65,
0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49,
0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x05, 0x20, 0x01,
0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xaf, 0x01, 0x0a, 0x21,
0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x69, 0x63, 0x74,
0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76,
0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x18,
0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74,
0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15,
0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72,
0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18,
0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x88,
0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x84, 0x01,
0x0a, 0x1e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x69,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63,
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x18, 0x64,
0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64,
0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x49, 0x64, 0x22, 0x91, 0x01, 0x0a, 0x20, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65,
0x54, 0x61, 0x73, 0x6b, 0x41, 0x77, 0x61, 0x69, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c,
0x65, 0x74, 0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72,
0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72,
0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18,
0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x64, 0x12,
0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03,
0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x1e, 0x44, 0x75, 0x72,
0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x74,
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x77,
0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0f, 0x77, 0x61, 0x69, 0x74,
0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x24, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61,
0x73, 0x6b, 0x41, 0x77, 0x61, 0x69, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
0x65, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67,
0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0xc4, 0x02, 0x0a, 0x12, 0x44, 0x75, 0x72, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f,
0x0a, 0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65,
0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72,
0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x48, 0x00, 0x52,
0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12,
0x33, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45,
0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x65,
0x76, 0x65, 0x6e, 0x74, 0x12, 0x52, 0x0a, 0x10, 0x65, 0x76, 0x69, 0x63, 0x74, 0x5f, 0x69, 0x6e,
0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25,
0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45,
0x76, 0x69, 0x63, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x65, 0x76, 0x69, 0x63, 0x74, 0x49, 0x6e,
0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x6b,
0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x22, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b,
0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x92,
0x02, 0x0a, 0x18, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x72,
0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64,
0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65,
0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64,
0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e,
0x61, 0x6c, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f,
0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12,
0x1b, 0x0a, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01,
0x28, 0x03, 0x52, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07,
0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e,
0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x74,
0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x44,
0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54,
0x79, 0x70, 0x65, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23,
0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18,
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x22, 0x8f, 0x03, 0x0a, 0x13, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54,
0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x72,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x67,
0x12, 0x1b, 0x0a, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x64, 0x12, 0x17, 0x0a,
0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x14, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x61,
0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x18, 0x05,
0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x6d, 0x65, 0x6d, 0x6f, 0x41, 0x6c, 0x72, 0x65, 0x61, 0x64,
0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x65, 0x64, 0x12, 0x33, 0x0a, 0x13, 0x6d, 0x65, 0x6d, 0x6f,
0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18,
0x06, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x11, 0x6d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x88, 0x01, 0x01, 0x42, 0x16, 0x0a,
0x14, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x70, 0x61,
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xdf, 0x01, 0x0a, 0x29, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74,
0x72, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74,
0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61,
0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10,
0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63,
0x68, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x72, 0x61, 0x6e,
0x63, 0x68, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18,
0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a,
0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07,
0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xaf, 0x01, 0x0a, 0x21, 0x44, 0x75, 0x72, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x69, 0x63, 0x74, 0x49, 0x6e, 0x76, 0x6f,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a,
0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72, 0x61,
0x62, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61,
0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49,
0x64, 0x12, 0x1b, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
0x09, 0x48, 0x00, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x09,
0x0a, 0x07, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x84, 0x01, 0x0a, 0x1e, 0x44, 0x75,
0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x69, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x10,
0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74,
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72, 0x61, 0x62,
0x6c, 0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72, 0x61, 0x62,
0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64,
0x22, 0x91, 0x01, 0x0a, 0x20, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b,
0x41, 0x77, 0x61, 0x69, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64,
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65,
0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69,
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65,
0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x1b,
0x0a, 0x09, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28,
0x03, 0x52, 0x08, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e,
0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f,
0x64, 0x65, 0x49, 0x64, 0x22, 0x8c, 0x01, 0x0a, 0x1e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65,
0x54, 0x61, 0x73, 0x6b, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x65,
0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b,
0x65, 0x72, 0x49, 0x64, 0x12, 0x4d, 0x0a, 0x0f, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f,
0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x41, 0x77,
0x61, 0x69, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x52, 0x0e, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x74, 0x72,
0x69, 0x65, 0x73, 0x22, 0xef, 0x01, 0x0a, 0x1e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54,
0x61, 0x73, 0x6b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f,
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12,
0x29, 0x0a, 0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x72,
0x61, 0x6e, 0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x62,
0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f,
0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64,
0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28,
0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x65,
0x6d, 0x6f, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x6d, 0x65,
0x6d, 0x6f, 0x4b, 0x65, 0x79, 0x22, 0x8f, 0x03, 0x0a, 0x12, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0f,
0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62,
0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x65, 0x67,
0x69, 0x73, 0x74, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x72,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x42, 0x0a,
0x0b, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54,
0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0a, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x41, 0x63,
0x6b, 0x12, 0x58, 0x0a, 0x0f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c,
0x65, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x76, 0x31, 0x2e,
0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74,
0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65,
0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x65, 0x6e, 0x74,
0x72, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x05, 0x65,
0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x76, 0x31, 0x2e,
0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f,
0x72, 0x12, 0x47, 0x0a, 0x0c, 0x65, 0x76, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63,
0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72,
0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x65,
0x76, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x99, 0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
0x65, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1d,
0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x42, 0x0a,
0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x22, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69,
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x72,
0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x22, 0x56, 0x0a, 0x1c, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x44, 0x75,
0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69,
0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x22, 0x5a, 0x0a, 0x0c, 0x44, 0x75, 0x72,
0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73,
0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b,
0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4b, 0x65,
0x79, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52,
0x04, 0x64, 0x61, 0x74, 0x61, 0x2a, 0xb0, 0x01, 0x0a, 0x14, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x29,
0x0a, 0x25, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x53, 0x4b, 0x5f, 0x54,
0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50,
0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x55, 0x52,
0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x53, 0x4b, 0x5f, 0x54, 0x52, 0x49, 0x47, 0x47, 0x45,
0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x52, 0x55, 0x4e, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22,
0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x53, 0x4b, 0x5f, 0x54, 0x52, 0x49,
0x47, 0x47, 0x45, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x46,
0x4f, 0x52, 0x10, 0x02, 0x12, 0x22, 0x0a, 0x1e, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x5f,
0x54, 0x41, 0x53, 0x4b, 0x5f, 0x54, 0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x5f, 0x4b, 0x49, 0x4e,
0x44, 0x5f, 0x4d, 0x45, 0x4d, 0x4f, 0x10, 0x03, 0x2a, 0x6b, 0x0a, 0x14, 0x44, 0x75, 0x72, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65,
0x12, 0x27, 0x0a, 0x23, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x53, 0x4b,
0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50,
0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2a, 0x0a, 0x26, 0x44, 0x55, 0x52,
0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x53, 0x4b, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x44, 0x45, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e,
0x49, 0x53, 0x4d, 0x10, 0x01, 0x32, 0x84, 0x02, 0x0a, 0x0c, 0x56, 0x31, 0x44, 0x69, 0x73, 0x70,
0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x0b, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x16, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62,
0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e,
0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x33, 0x0a,
0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x76,
0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x65, 0x76, 0x65,
0x6e, 0x74, 0x12, 0x52, 0x0a, 0x10, 0x65, 0x76, 0x69, 0x63, 0x74, 0x5f, 0x69, 0x6e, 0x76, 0x6f,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76,
0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x69,
0x63, 0x74, 0x49, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x65, 0x76, 0x69, 0x63, 0x74, 0x49, 0x6e, 0x76, 0x6f,
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72,
0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e,
0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x57, 0x6f,
0x72, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x48, 0x00, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75,
0x73, 0x12, 0x49, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x6d, 0x65,
0x6d, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75,
0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74,
0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c,
0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x4d, 0x65, 0x6d, 0x6f, 0x42, 0x09, 0x0a, 0x07,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x92, 0x02, 0x0a, 0x18, 0x44, 0x75, 0x72, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x37, 0x0a, 0x18, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x5f,
0x74, 0x61, 0x73, 0x6b, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x64, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54,
0x61, 0x73, 0x6b, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x29, 0x0a,
0x10, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x69, 0x6e, 0x76, 0x6f, 0x63, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x72, 0x61, 0x6e,
0x63, 0x68, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x72, 0x61,
0x6e, 0x63, 0x68, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64,
0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x37,
0x0a, 0x0a, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01,
0x28, 0x0e, 0x32, 0x18, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54,
0x61, 0x73, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x52, 0x09, 0x65, 0x72,
0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8f, 0x03, 0x0a,
0x13, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x50, 0x0a, 0x0f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e,
0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x14,
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45,
0x76, 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
0x65, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73,
0x74, 0x65, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x15, 0x4c, 0x69, 0x73,
0x74, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x12, 0x20, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x46, 0x6f,
0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x42, 0x5a, 0x40,
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68,
0x65, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2f, 0x69,
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x57, 0x6f,
0x72, 0x6b, 0x65, 0x72, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72,
0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x0b, 0x74, 0x72, 0x69, 0x67, 0x67, 0x65,
0x72, 0x5f, 0x61, 0x63, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x76, 0x31,
0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e,
0x74, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0a,
0x74, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x41, 0x63, 0x6b, 0x12, 0x58, 0x0a, 0x0f, 0x65, 0x6e,
0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65,
0x54, 0x61, 0x73, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c,
0x65, 0x74, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x04, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65,
0x54, 0x61, 0x73, 0x6b, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x47, 0x0a, 0x0c, 0x65, 0x76,
0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x22, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73,
0x6b, 0x45, 0x76, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x65, 0x76, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x41, 0x63, 0x6b, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x99,
0x01, 0x0a, 0x1b, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62,
0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17,
0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61,
0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67,
0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x31, 0x2e,
0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74,
0x65, 0x6e, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0a,
0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x1e, 0x0a, 0x1c, 0x52, 0x65,
0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x56, 0x0a, 0x1c, 0x4c, 0x69,
0x73, 0x74, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61,
0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73,
0x6b, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65,
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4b,
0x65, 0x79, 0x22, 0x5a, 0x0a, 0x0c, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65,
0x6e, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x73, 0x6b, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73,
0x69, 0x67, 0x6e, 0x61, 0x6c, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61,
0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x2a, 0xb0,
0x01, 0x0a, 0x14, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x45, 0x76,
0x65, 0x6e, 0x74, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x25, 0x44, 0x55, 0x52, 0x41, 0x42,
0x4c, 0x45, 0x5f, 0x54, 0x41, 0x53, 0x4b, 0x5f, 0x54, 0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x5f,
0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41,
0x53, 0x4b, 0x5f, 0x54, 0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f,
0x52, 0x55, 0x4e, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45,
0x5f, 0x54, 0x41, 0x53, 0x4b, 0x5f, 0x54, 0x52, 0x49, 0x47, 0x47, 0x45, 0x52, 0x5f, 0x4b, 0x49,
0x4e, 0x44, 0x5f, 0x57, 0x41, 0x49, 0x54, 0x5f, 0x46, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x22, 0x0a,
0x1e, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x53, 0x4b, 0x5f, 0x54, 0x52,
0x49, 0x47, 0x47, 0x45, 0x52, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x45, 0x4d, 0x4f, 0x10,
0x03, 0x2a, 0x6b, 0x0a, 0x14, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b,
0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x27, 0x0a, 0x23, 0x44, 0x55, 0x52,
0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41, 0x53, 0x4b, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
0x10, 0x00, 0x12, 0x2a, 0x0a, 0x26, 0x44, 0x55, 0x52, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x54, 0x41,
0x53, 0x4b, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4e, 0x4f,
0x4e, 0x44, 0x45, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, 0x49, 0x53, 0x4d, 0x10, 0x01, 0x32, 0x84,
0x02, 0x0a, 0x0c, 0x56, 0x31, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12,
0x44, 0x0a, 0x0b, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x16,
0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61,
0x62, 0x6c, 0x65, 0x54, 0x61, 0x73, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x28, 0x01, 0x30, 0x01, 0x12, 0x5b, 0x0a, 0x14, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65,
0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1f, 0x2e,
0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62,
0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20,
0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x75, 0x72, 0x61,
0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
0x22, 0x00, 0x12, 0x51, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x44,
0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x76, 0x31,
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x46, 0x6f, 0x72, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c,
0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e,
0x76, 0x31, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22,
0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2d, 0x64, 0x65, 0x76, 0x2f,
0x68, 0x61, 0x74, 0x63, 0x68, 0x65, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x64,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
@@ -1476,7 +1635,7 @@ func file_v1_dispatcher_proto_rawDescGZIP() []byte {
}
var file_v1_dispatcher_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_v1_dispatcher_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
var file_v1_dispatcher_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
var file_v1_dispatcher_proto_goTypes = []interface{}{
(DurableTaskEventKind)(0), // 0: v1.DurableTaskEventKind
(DurableTaskErrorType)(0), // 1: v1.DurableTaskErrorType
@@ -1489,43 +1648,45 @@ var file_v1_dispatcher_proto_goTypes = []interface{}{
(*DurableTaskEvictionAckResponse)(nil), // 8: v1.DurableTaskEvictionAckResponse
(*DurableTaskAwaitedCompletedEntry)(nil), // 9: v1.DurableTaskAwaitedCompletedEntry
(*DurableTaskWorkerStatusRequest)(nil), // 10: v1.DurableTaskWorkerStatusRequest
(*DurableTaskRequest)(nil), // 11: v1.DurableTaskRequest
(*DurableTaskErrorResponse)(nil), // 12: v1.DurableTaskErrorResponse
(*DurableTaskResponse)(nil), // 13: v1.DurableTaskResponse
(*RegisterDurableEventRequest)(nil), // 14: v1.RegisterDurableEventRequest
(*RegisterDurableEventResponse)(nil), // 15: v1.RegisterDurableEventResponse
(*ListenForDurableEventRequest)(nil), // 16: v1.ListenForDurableEventRequest
(*DurableEvent)(nil), // 17: v1.DurableEvent
(*DurableEventListenerConditions)(nil), // 18: v1.DurableEventListenerConditions
(*TriggerWorkflowRequest)(nil), // 19: v1.TriggerWorkflowRequest
(*DurableTaskCompleteMemoRequest)(nil), // 11: v1.DurableTaskCompleteMemoRequest
(*DurableTaskRequest)(nil), // 12: v1.DurableTaskRequest
(*DurableTaskErrorResponse)(nil), // 13: v1.DurableTaskErrorResponse
(*DurableTaskResponse)(nil), // 14: v1.DurableTaskResponse
(*RegisterDurableEventRequest)(nil), // 15: v1.RegisterDurableEventRequest
(*RegisterDurableEventResponse)(nil), // 16: v1.RegisterDurableEventResponse
(*ListenForDurableEventRequest)(nil), // 17: v1.ListenForDurableEventRequest
(*DurableEvent)(nil), // 18: v1.DurableEvent
(*DurableEventListenerConditions)(nil), // 19: v1.DurableEventListenerConditions
(*TriggerWorkflowRequest)(nil), // 20: v1.TriggerWorkflowRequest
}
var file_v1_dispatcher_proto_depIdxs = []int32{
0, // 0: v1.DurableTaskEventRequest.kind:type_name -> v1.DurableTaskEventKind
18, // 1: v1.DurableTaskEventRequest.wait_for_conditions:type_name -> v1.DurableEventListenerConditions
19, // 2: v1.DurableTaskEventRequest.trigger_opts:type_name -> v1.TriggerWorkflowRequest
19, // 1: v1.DurableTaskEventRequest.wait_for_conditions:type_name -> v1.DurableEventListenerConditions
20, // 2: v1.DurableTaskEventRequest.trigger_opts:type_name -> v1.TriggerWorkflowRequest
9, // 3: v1.DurableTaskWorkerStatusRequest.waiting_entries:type_name -> v1.DurableTaskAwaitedCompletedEntry
2, // 4: v1.DurableTaskRequest.register_worker:type_name -> v1.DurableTaskRequestRegisterWorker
4, // 5: v1.DurableTaskRequest.event:type_name -> v1.DurableTaskEventRequest
7, // 6: v1.DurableTaskRequest.evict_invocation:type_name -> v1.DurableTaskEvictInvocationRequest
10, // 7: v1.DurableTaskRequest.worker_status:type_name -> v1.DurableTaskWorkerStatusRequest
1, // 8: v1.DurableTaskErrorResponse.error_type:type_name -> v1.DurableTaskErrorType
3, // 9: v1.DurableTaskResponse.register_worker:type_name -> v1.DurableTaskResponseRegisterWorker
5, // 10: v1.DurableTaskResponse.trigger_ack:type_name -> v1.DurableTaskEventAckResponse
6, // 11: v1.DurableTaskResponse.entry_completed:type_name -> v1.DurableTaskEventLogEntryCompletedResponse
12, // 12: v1.DurableTaskResponse.error:type_name -> v1.DurableTaskErrorResponse
8, // 13: v1.DurableTaskResponse.eviction_ack:type_name -> v1.DurableTaskEvictionAckResponse
18, // 14: v1.RegisterDurableEventRequest.conditions:type_name -> v1.DurableEventListenerConditions
11, // 15: v1.V1Dispatcher.DurableTask:input_type -> v1.DurableTaskRequest
14, // 16: v1.V1Dispatcher.RegisterDurableEvent:input_type -> v1.RegisterDurableEventRequest
16, // 17: v1.V1Dispatcher.ListenForDurableEvent:input_type -> v1.ListenForDurableEventRequest
13, // 18: v1.V1Dispatcher.DurableTask:output_type -> v1.DurableTaskResponse
15, // 19: v1.V1Dispatcher.RegisterDurableEvent:output_type -> v1.RegisterDurableEventResponse
17, // 20: v1.V1Dispatcher.ListenForDurableEvent:output_type -> v1.DurableEvent
18, // [18:21] is the sub-list for method output_type
15, // [15:18] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
11, // 8: v1.DurableTaskRequest.complete_memo:type_name -> v1.DurableTaskCompleteMemoRequest
1, // 9: v1.DurableTaskErrorResponse.error_type:type_name -> v1.DurableTaskErrorType
3, // 10: v1.DurableTaskResponse.register_worker:type_name -> v1.DurableTaskResponseRegisterWorker
5, // 11: v1.DurableTaskResponse.trigger_ack:type_name -> v1.DurableTaskEventAckResponse
6, // 12: v1.DurableTaskResponse.entry_completed:type_name -> v1.DurableTaskEventLogEntryCompletedResponse
13, // 13: v1.DurableTaskResponse.error:type_name -> v1.DurableTaskErrorResponse
8, // 14: v1.DurableTaskResponse.eviction_ack:type_name -> v1.DurableTaskEvictionAckResponse
19, // 15: v1.RegisterDurableEventRequest.conditions:type_name -> v1.DurableEventListenerConditions
12, // 16: v1.V1Dispatcher.DurableTask:input_type -> v1.DurableTaskRequest
15, // 17: v1.V1Dispatcher.RegisterDurableEvent:input_type -> v1.RegisterDurableEventRequest
17, // 18: v1.V1Dispatcher.ListenForDurableEvent:input_type -> v1.ListenForDurableEventRequest
14, // 19: v1.V1Dispatcher.DurableTask:output_type -> v1.DurableTaskResponse
16, // 20: v1.V1Dispatcher.RegisterDurableEvent:output_type -> v1.RegisterDurableEventResponse
18, // 21: v1.V1Dispatcher.ListenForDurableEvent:output_type -> v1.DurableEvent
19, // [19:22] is the sub-list for method output_type
16, // [16:19] is the sub-list for method input_type
16, // [16:16] is the sub-list for extension type_name
16, // [16:16] is the sub-list for extension extendee
0, // [0:16] is the sub-list for field type_name
}
func init() { file_v1_dispatcher_proto_init() }
@@ -1645,7 +1806,7 @@ func file_v1_dispatcher_proto_init() {
}
}
file_v1_dispatcher_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DurableTaskRequest); i {
switch v := v.(*DurableTaskCompleteMemoRequest); i {
case 0:
return &v.state
case 1:
@@ -1657,7 +1818,7 @@ func file_v1_dispatcher_proto_init() {
}
}
file_v1_dispatcher_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DurableTaskErrorResponse); i {
switch v := v.(*DurableTaskRequest); i {
case 0:
return &v.state
case 1:
@@ -1669,7 +1830,7 @@ func file_v1_dispatcher_proto_init() {
}
}
file_v1_dispatcher_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DurableTaskResponse); i {
switch v := v.(*DurableTaskErrorResponse); i {
case 0:
return &v.state
case 1:
@@ -1681,7 +1842,7 @@ func file_v1_dispatcher_proto_init() {
}
}
file_v1_dispatcher_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegisterDurableEventRequest); i {
switch v := v.(*DurableTaskResponse); i {
case 0:
return &v.state
case 1:
@@ -1693,7 +1854,7 @@ func file_v1_dispatcher_proto_init() {
}
}
file_v1_dispatcher_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RegisterDurableEventResponse); i {
switch v := v.(*RegisterDurableEventRequest); i {
case 0:
return &v.state
case 1:
@@ -1705,7 +1866,7 @@ func file_v1_dispatcher_proto_init() {
}
}
file_v1_dispatcher_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListenForDurableEventRequest); i {
switch v := v.(*RegisterDurableEventResponse); i {
case 0:
return &v.state
case 1:
@@ -1717,6 +1878,18 @@ func file_v1_dispatcher_proto_init() {
}
}
file_v1_dispatcher_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ListenForDurableEventRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_v1_dispatcher_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DurableEvent); i {
case 0:
return &v.state
@@ -1730,14 +1903,16 @@ func file_v1_dispatcher_proto_init() {
}
}
file_v1_dispatcher_proto_msgTypes[2].OneofWrappers = []interface{}{}
file_v1_dispatcher_proto_msgTypes[3].OneofWrappers = []interface{}{}
file_v1_dispatcher_proto_msgTypes[5].OneofWrappers = []interface{}{}
file_v1_dispatcher_proto_msgTypes[9].OneofWrappers = []interface{}{
file_v1_dispatcher_proto_msgTypes[10].OneofWrappers = []interface{}{
(*DurableTaskRequest_RegisterWorker)(nil),
(*DurableTaskRequest_Event)(nil),
(*DurableTaskRequest_EvictInvocation)(nil),
(*DurableTaskRequest_WorkerStatus)(nil),
(*DurableTaskRequest_CompleteMemo)(nil),
}
file_v1_dispatcher_proto_msgTypes[11].OneofWrappers = []interface{}{
file_v1_dispatcher_proto_msgTypes[12].OneofWrappers = []interface{}{
(*DurableTaskResponse_RegisterWorker)(nil),
(*DurableTaskResponse_TriggerAck)(nil),
(*DurableTaskResponse_EntryCompleted)(nil),
@@ -1750,7 +1925,7 @@ func file_v1_dispatcher_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_v1_dispatcher_proto_rawDesc,
NumEnums: 2,
NumMessages: 16,
NumMessages: 17,
NumExtensions: 0,
NumServices: 1,
},
+92 -17
View File
@@ -40,13 +40,20 @@ type SatisfiedEventWithPayload struct {
}
type IngestDurableTaskEventOpts struct {
TenantId uuid.UUID `validate:"required"`
Task *sqlcv1.FlattenExternalIdsRow `validate:"required"`
Kind sqlcv1.V1DurableEventLogKind `validate:"required,oneof=RUN WAIT_FOR MEMO"`
Payload []byte
TenantId uuid.UUID `validate:"required"`
Task *sqlcv1.FlattenExternalIdsRow `validate:"required"`
Kind sqlcv1.V1DurableEventLogKind `validate:"required,oneof=RUN WAIT_FOR MEMO"`
Payload []byte
InvocationCount int32
// optional, used only when kind = WAIT_FOR
WaitForConditions []CreateExternalSignalConditionOpt
InvocationCount int32
TriggerOpts *WorkflowNameTriggerOpts
// optional, used only when kind = RUN
TriggerOpts *WorkflowNameTriggerOpts
// optional, used only when kind = MEMO
MemoKey []byte
}
type IngestDurableTaskEventResult struct {
@@ -54,8 +61,9 @@ type IngestDurableTaskEventResult struct {
NodeId int64
InvocationCount int32
IsSatisfied bool
ResultPayload []byte
IsSatisfied bool
ResultPayload []byte
AlreadyExisted bool
// Populated for RUNTRIGGERED: the tasks/DAGs created by the child spawn.
CreatedTasks []*V1TaskWithPayload
@@ -74,12 +82,23 @@ type IncrementDurableTaskInvocationCountsOpts struct {
TaskInsertedAt pgtype.Timestamptz
}
type CompleteMemoEntryOpts struct {
TenantId uuid.UUID
TaskExternalId uuid.UUID
InvocationCount int32
BranchId int64
NodeId int64
MemoKey []byte
Payload []byte
}
type DurableEventsRepository interface {
IngestDurableTaskEvent(ctx context.Context, opts IngestDurableTaskEventOpts) (*IngestDurableTaskEventResult, error)
HandleFork(ctx context.Context, tenantId uuid.UUID, nodeId int64, task *sqlcv1.FlattenExternalIdsRow) (*HandleForkResult, error)
GetSatisfiedDurableEvents(ctx context.Context, tenantId uuid.UUID, events []TaskExternalIdNodeIdBranchId) ([]*SatisfiedEventWithPayload, error)
GetDurableTaskInvocationCounts(ctx context.Context, tenantId uuid.UUID, tasks []IdInsertedAt) (map[IdInsertedAt]*int32, error)
CompleteMemoEntry(ctx context.Context, opts CompleteMemoEntryOpts) error
}
type durableEventsRepository struct {
@@ -126,7 +145,6 @@ func (r *durableEventsRepository) getOrCreateEventLogEntry(
tx sqlcv1.DBTX,
opts GetOrCreateLogEntryOpts,
) (*EventLogEntryWithPayloads, error) {
entryExternalId := uuid.New()
alreadyExisted := true
entry, err := r.queries.GetDurableEventLogEntry(ctx, tx, sqlcv1.GetDurableEventLogEntryParams{
Durabletaskid: opts.DurableTaskId,
@@ -146,7 +164,7 @@ func (r *durableEventsRepository) getOrCreateEventLogEntry(
alreadyExisted = false
entry, err = r.queries.CreateDurableEventLogEntry(ctx, tx, sqlcv1.CreateDurableEventLogEntryParams{
Tenantid: opts.TenantId,
Externalid: entryExternalId,
Externalid: uuid.New(),
Durabletaskid: opts.DurableTaskId,
Durabletaskinsertedat: opts.DurableTaskInsertedAt,
Kind: opts.Kind,
@@ -499,6 +517,7 @@ func (r *durableEventsRepository) IngestDurableTaskEvent(ctx context.Context, op
var inputPayload []byte
var resultPayload []byte
var idempotencyKey []byte
isSatisfied := false
switch opts.Kind {
@@ -513,17 +532,23 @@ func (r *durableEventsRepository) IngestDurableTaskEvent(ctx context.Context, op
return nil, fmt.Errorf("failed to marshal trigger opts: %w", err)
}
case sqlcv1.V1DurableEventLogKindMEMO:
// for memoization, we don't need to wait for anything before marking the entry as satisfied since it's just a cache entry
isSatisfied = true
resultPayload = opts.Payload
// if we get a payload here, it means we should persist it and mark the memo event as having been satisfied,
// since it's now replayable by retrieving that payload
if len(opts.Payload) > 0 {
isSatisfied = true
resultPayload = opts.Payload
}
idempotencyKey = opts.MemoKey
default:
return nil, fmt.Errorf("unsupported durable event log entry kind: %s", opts.Kind)
}
idempotencyKey, err := r.createIdempotencyKey(opts)
if opts.Kind != sqlcv1.V1DurableEventLogKindMEMO {
idempotencyKey, err = r.createIdempotencyKey(opts)
if err != nil {
return nil, fmt.Errorf("failed to create idempotency key: %w", err)
if err != nil {
return nil, fmt.Errorf("failed to create idempotency key: %w", err)
}
}
logEntry, err := r.getOrCreateEventLogEntry(
@@ -569,7 +594,7 @@ func (r *durableEventsRepository) IngestDurableTaskEvent(ctx context.Context, op
return nil, fmt.Errorf("failed to handle trigger runs: %w", err)
}
case sqlcv1.V1DurableEventLogKindMEMO:
// TODO-DURABLE: memo here
// do nothing - we don't need to do anything downstream since memo just writes the cache entry and returns
default:
return nil, fmt.Errorf("unsupported durable event log entry kind: %s", opts.Kind)
}
@@ -594,6 +619,7 @@ func (r *durableEventsRepository) IngestDurableTaskEvent(ctx context.Context, op
BranchId: branchId,
InvocationCount: opts.InvocationCount,
IsSatisfied: logEntry.Entry.IsSatisfied,
AlreadyExisted: logEntry.AlreadyExisted,
ResultPayload: logEntry.ResultPayload,
CreatedTasks: spawnedTasks,
CreatedDAGs: spawnedDAGs,
@@ -700,6 +726,55 @@ func (r *durableEventsRepository) handleTriggerRuns(ctx context.Context, tx *Opt
return createdDAGs, createdTasks, nil
}
func (r *durableEventsRepository) CompleteMemoEntry(ctx context.Context, opts CompleteMemoEntryOpts) error {
task, err := r.GetTaskByExternalId(ctx, opts.TenantId, opts.TaskExternalId, false)
if err != nil {
return fmt.Errorf("failed to get task by external id: %w", err)
}
entry, err := r.queries.GetDurableEventLogEntry(ctx, r.pool, sqlcv1.GetDurableEventLogEntryParams{
Durabletaskid: task.ID,
Durabletaskinsertedat: task.InsertedAt,
Nodeid: opts.NodeId,
Branchid: opts.BranchId,
})
if err != nil {
return fmt.Errorf("failed to get durable event log entry at branch %d node %d: %w", opts.BranchId, opts.NodeId, err)
}
if entry.IsSatisfied {
return nil
}
_, err = r.queries.MarkDurableEventLogEntrySatisfied(ctx, r.pool, sqlcv1.MarkDurableEventLogEntrySatisfiedParams{
Durabletaskid: task.ID,
Durabletaskinsertedat: task.InsertedAt,
Nodeid: opts.NodeId,
Branchid: opts.BranchId,
})
if err != nil {
return fmt.Errorf("failed to mark memo entry as satisfied: %w", err)
}
if len(opts.Payload) > 0 {
err = r.payloadStore.Store(ctx, r.pool, StorePayloadOpts{
Id: entry.ID,
InsertedAt: entry.InsertedAt,
ExternalId: entry.ExternalID,
Type: sqlcv1.V1PayloadTypeDURABLEEVENTLOGENTRYRESULTDATA,
Payload: opts.Payload,
TenantId: opts.TenantId,
})
if err != nil {
return fmt.Errorf("failed to store memo result payload: %w", err)
}
}
return nil
}
func (r *durableEventsRepository) HandleFork(ctx context.Context, tenantId uuid.UUID, nodeId int64, task *sqlcv1.FlattenExternalIdsRow) (*HandleForkResult, error) {
optTx, err := r.PrepareOptimisticTx(ctx)
if err != nil {
@@ -150,6 +150,17 @@ WHERE
AND e.is_satisfied
;
-- name: MarkDurableEventLogEntrySatisfied :one
UPDATE v1_durable_event_log_entry
SET is_satisfied = true
WHERE durable_task_id = @durableTaskId::BIGINT
AND durable_task_inserted_at = @durableTaskInsertedAt::TIMESTAMPTZ
AND branch_id = @branchId::BIGINT
AND node_id = @nodeId::BIGINT
RETURNING *
;
-- name: GetDurableTaskLogFiles :many
WITH inputs AS (
SELECT
@@ -375,6 +375,50 @@ func (q *Queries) ListSatisfiedEntries(ctx context.Context, db DBTX, arg ListSat
return items, nil
}
const markDurableEventLogEntrySatisfied = `-- name: MarkDurableEventLogEntrySatisfied :one
UPDATE v1_durable_event_log_entry
SET is_satisfied = true
WHERE durable_task_id = $1::BIGINT
AND durable_task_inserted_at = $2::TIMESTAMPTZ
AND branch_id = $3::BIGINT
AND node_id = $4::BIGINT
RETURNING tenant_id, external_id, inserted_at, id, durable_task_id, durable_task_inserted_at, kind, node_id, parent_node_id, branch_id, parent_branch_id, invocation_count, idempotency_key, is_satisfied
`
type MarkDurableEventLogEntrySatisfiedParams struct {
Durabletaskid int64 `json:"durabletaskid"`
Durabletaskinsertedat pgtype.Timestamptz `json:"durabletaskinsertedat"`
Branchid int64 `json:"branchid"`
Nodeid int64 `json:"nodeid"`
}
func (q *Queries) MarkDurableEventLogEntrySatisfied(ctx context.Context, db DBTX, arg MarkDurableEventLogEntrySatisfiedParams) (*V1DurableEventLogEntry, error) {
row := db.QueryRow(ctx, markDurableEventLogEntrySatisfied,
arg.Durabletaskid,
arg.Durabletaskinsertedat,
arg.Branchid,
arg.Nodeid,
)
var i V1DurableEventLogEntry
err := row.Scan(
&i.TenantID,
&i.ExternalID,
&i.InsertedAt,
&i.ID,
&i.DurableTaskID,
&i.DurableTaskInsertedAt,
&i.Kind,
&i.NodeID,
&i.ParentNodeID,
&i.BranchID,
&i.ParentBranchID,
&i.InvocationCount,
&i.IdempotencyKey,
&i.IsSatisfied,
)
return &i, err
}
const updateDurableEventLogEntriesSatisfied = `-- name: UpdateDurableEventLogEntriesSatisfied :many
WITH inputs AS (
SELECT
@@ -2,6 +2,7 @@ import asyncio
import time
import pytest
from uuid import uuid4
from examples.durable.worker import (
EVENT_KEY,
@@ -14,6 +15,8 @@ from examples.durable.worker import (
durable_spawn_dag,
durable_non_determinism,
durable_replay_reset,
memo_task,
MemoInput,
)
from hatchet_sdk import Hatchet
@@ -186,3 +189,22 @@ async def test_durable_replay_reset(hatchet: Hatchet, node_id: int) -> None:
sleeps_to_redo = 3 - node_id + 1
assert reset_elapsed >= sleeps_to_redo * REPLAY_RESET_SLEEP_TIME
@pytest.mark.asyncio(loop_scope="session")
async def test_durable_memoization_via_replay(hatchet: Hatchet) -> None:
message = str(uuid4())
start = time.time()
ref = await memo_task.aio_run_no_wait(MemoInput(message=message))
result_1 = await ref.aio_result()
duration_1 = time.time() - start
await hatchet.runs.aio_replay(ref.workflow_run_id)
start = time.time()
result_2 = await ref.aio_result()
duration_2 = time.time() - start
assert duration_1 >= SLEEP_TIME
assert duration_2 < 1
assert result_1.message == result_2.message
+27
View File
@@ -278,6 +278,33 @@ async def durable_replay_reset(
)
class SleepResult(BaseModel):
message: str
duration: float
class MemoInput(BaseModel):
message: str
async def expensive_computation(message: str) -> SleepResult:
await asyncio.sleep(SLEEP_TIME)
return SleepResult(message=message, duration=SLEEP_TIME)
@hatchet.durable_task(input_validator=MemoInput)
async def memo_task(input: MemoInput, ctx: DurableContext) -> SleepResult:
start = time.time()
res = await ctx.aio_memo(
expensive_computation,
SleepResult,
input.message,
)
return SleepResult(message=res.message, duration=time.time() - start)
def main() -> None:
worker = hatchet.worker(
"durable-worker",
+2
View File
@@ -41,6 +41,7 @@ from examples.durable.worker import (
durable_spawn_dag,
durable_non_determinism,
durable_replay_reset,
memo_task,
)
from examples.durable_eviction.worker import (
child_task as eviction_child_task,
@@ -135,6 +136,7 @@ def main() -> None:
dag_child_workflow,
durable_non_determinism,
durable_replay_reset,
memo_task,
evictable_sleep,
evictable_wait_for_event,
evictable_child_spawn,
@@ -2,17 +2,22 @@ import asyncio
import json
from collections.abc import AsyncIterator
from contextlib import suppress
from dataclasses import dataclass
from typing import cast
import grpc.aio
from pydantic import BaseModel
from typing_extensions import Self
from typing_extensions import Never, Self
from hatchet_sdk.clients.admin import AdminClient, TriggerWorkflowOptions
from hatchet_sdk.clients.admin import (
AdminClient,
TriggerWorkflowOptions,
)
from hatchet_sdk.config import ClientConfig
from hatchet_sdk.connection import new_conn
from hatchet_sdk.contracts.v1.dispatcher_pb2 import (
DurableTaskAwaitedCompletedEntry,
DurableTaskCompleteMemoRequest,
DurableTaskErrorType,
DurableTaskEventKind,
DurableTaskEventLogEntryCompletedResponse,
@@ -33,11 +38,39 @@ from hatchet_sdk.utils.typing import JSONSerializableMapping
DEFAULT_RECONNECT_INTERVAL = 3 # seconds
@dataclass(frozen=True)
class WaitForEvent:
wait_for_conditions: DurableEventListenerConditions
@dataclass(frozen=True)
class RunChildEvent:
workflow_name: str
input: str | None
trigger_workflow_opts: TriggerWorkflowOptions
@dataclass(frozen=True)
class MemoEvent:
memo_key: bytes
result: str | None
DurableTaskSendEvent = WaitForEvent | RunChildEvent | MemoEvent
class MaybeCachedMemoEntry(BaseModel):
found: bool
data: bytes | None = None
class DurableTaskEventAck(BaseModel):
invocation_count: int
durable_task_external_id: str
branch_id: int
node_id: int
memo_already_existed: bool
memo_result_payload: bytes | None = None
class DurableTaskEventLogEntryResult(BaseModel):
@@ -271,6 +304,8 @@ class DurableEventListener:
durable_task_external_id=trigger_ack.durable_task_external_id,
node_id=trigger_ack.node_id,
branch_id=trigger_ack.branch_id,
memo_already_existed=trigger_ack.memo_already_existed,
memo_result_payload=trigger_ack.memo_result_payload,
)
)
del self._pending_event_acks[event_key]
@@ -365,12 +400,7 @@ class DurableEventListener:
self,
durable_task_external_id: str,
invocation_count: int,
kind: DurableTaskEventKind,
payload: str | None = None,
wait_for_conditions: DurableEventListenerConditions | None = None,
# todo: combine these? or separate methods? or overload?
workflow_name: str | None = None,
trigger_workflow_opts: TriggerWorkflowOptions | None = None,
event: DurableTaskSendEvent,
) -> DurableTaskEventAck:
if self._request_queue is None:
raise RuntimeError("Client not started")
@@ -379,31 +409,45 @@ class DurableEventListener:
future: asyncio.Future[DurableTaskEventAck] = asyncio.Future()
self._pending_event_acks[key] = future
_trigger_opts = (
self.admin_client._create_workflow_run_request(
workflow_name=workflow_name,
input=payload,
options=trigger_workflow_opts or TriggerWorkflowOptions(),
if isinstance(event, RunChildEvent):
_trigger_opts = self.admin_client._create_workflow_run_request(
workflow_name=event.workflow_name,
input=event.input,
options=event.trigger_workflow_opts,
)
if workflow_name
else None
)
event_request = DurableTaskEventRequest(
durable_task_external_id=durable_task_external_id,
invocation_count=invocation_count,
kind=kind,
trigger_opts=_trigger_opts,
)
event_request = DurableTaskEventRequest(
durable_task_external_id=durable_task_external_id,
invocation_count=invocation_count,
kind=DurableTaskEventKind.DURABLE_TASK_TRIGGER_KIND_RUN,
trigger_opts=_trigger_opts,
)
if payload is not None:
event_request.payload = json.dumps(payload).encode("utf-8")
elif isinstance(event, WaitForEvent):
event_request = DurableTaskEventRequest(
durable_task_external_id=durable_task_external_id,
invocation_count=invocation_count,
kind=DurableTaskEventKind.DURABLE_TASK_TRIGGER_KIND_WAIT_FOR,
)
if wait_for_conditions is not None:
event_request.wait_for_conditions.CopyFrom(wait_for_conditions)
event_request.wait_for_conditions.CopyFrom(event.wait_for_conditions)
request = DurableTaskRequest(event=event_request)
await self._request_queue.put(request)
elif isinstance(event, MemoEvent):
event_request = DurableTaskEventRequest(
durable_task_external_id=durable_task_external_id,
invocation_count=invocation_count,
kind=DurableTaskEventKind.DURABLE_TASK_TRIGGER_KIND_MEMO,
memo_key=event.memo_key,
)
if event.result is not None:
event_request.payload = event.result.encode("utf-8")
else:
e: Never = event
raise ValueError(f"Unknown durable task send event: {e}")
await self._request_queue.put(DurableTaskRequest(event=event_request))
return await future
@@ -494,3 +538,28 @@ class DurableEventListener:
f"Eviction ack timed out after {self._EVICTION_ACK_TIMEOUT_S:.0f}s "
f"for task {durable_task_external_id} invocation {invocation_count}"
) from err
async def send_memo_completed_notification(
self,
durable_task_external_id: str,
node_id: int,
branch_id: int,
invocation_count: int,
memo_key: bytes,
memo_result_payload: bytes | None,
) -> None:
if self._request_queue is None:
raise RuntimeError("Client not started")
await self._request_queue.put(
DurableTaskRequest(
complete_memo=DurableTaskCompleteMemoRequest(
durable_task_external_id=durable_task_external_id,
invocation_count=invocation_count,
branch_id=branch_id,
node_id=node_id,
memo_key=memo_key,
payload=memo_result_payload,
)
)
)
+97 -10
View File
@@ -1,11 +1,15 @@
from __future__ import annotations
import asyncio
import hashlib
import json
from collections.abc import Awaitable, Callable
from datetime import timedelta
from typing import TYPE_CHECKING, Any, cast
from typing import TYPE_CHECKING, Any, ParamSpec, TypeVar, cast
from warnings import warn
from pydantic import TypeAdapter
from hatchet_sdk.clients.admin import AdminClient, TriggerWorkflowOptions
from hatchet_sdk.clients.dispatcher.dispatcher import ( # type: ignore[attr-defined]
Action,
@@ -14,6 +18,9 @@ from hatchet_sdk.clients.dispatcher.dispatcher import ( # type: ignore[attr-def
from hatchet_sdk.clients.events import EventClient
from hatchet_sdk.clients.listeners.durable_event_listener import (
DurableEventListener,
MemoEvent,
RunChildEvent,
WaitForEvent,
)
from hatchet_sdk.conditions import (
OrGroup,
@@ -23,11 +30,16 @@ from hatchet_sdk.conditions import (
flatten_conditions,
)
from hatchet_sdk.context.worker_context import WorkerContext
from hatchet_sdk.contracts.v1.dispatcher_pb2 import DurableTaskEventKind
from hatchet_sdk.exceptions import TaskRunError
from hatchet_sdk.features.runs import RunsClient
from hatchet_sdk.logger import logger
from hatchet_sdk.runnables.types import EmptyModel, R, TWorkflowInput
from hatchet_sdk.runnables.types import (
EmptyModel,
R,
TWorkflowInput,
ValidTaskReturnType,
)
from hatchet_sdk.serde import HATCHET_PYDANTIC_SENTINEL
from hatchet_sdk.utils.timedelta_to_expression import Duration, timedelta_to_expr
from hatchet_sdk.utils.typing import JSONSerializableMapping, LogLevel
from hatchet_sdk.worker.durable_eviction.instrumentation import (
@@ -36,6 +48,9 @@ from hatchet_sdk.worker.durable_eviction.instrumentation import (
from hatchet_sdk.worker.durable_eviction.manager import DurableEvictionManager
from hatchet_sdk.worker.runner.utils.capture_logs import AsyncLogSender, LogRecord
PMemo = ParamSpec("PMemo")
TMemo = TypeVar("TMemo", bound=ValidTaskReturnType)
if TYPE_CHECKING:
from hatchet_sdk.runnables.task import Task
from hatchet_sdk.runnables.workflow import (
@@ -43,6 +58,14 @@ if TYPE_CHECKING:
)
def _compute_memo_key(task_run_external_id: str, *args: Any, **kwargs: Any) -> bytes:
h = hashlib.sha256()
h.update(task_run_external_id.encode())
h.update(json.dumps(args, default=str, sort_keys=True).encode())
h.update(json.dumps(kwargs, default=str, sort_keys=True).encode())
return h.digest()
class Context:
def __init__(
self,
@@ -517,9 +540,7 @@ class DurableContext(Context):
ack = await self.durable_event_listener.send_event(
durable_task_external_id=self.step_run_id,
invocation_count=self.invocation_count,
kind=DurableTaskEventKind.DURABLE_TASK_TRIGGER_KIND_WAIT_FOR,
payload=None,
wait_for_conditions=conditions_proto,
event=WaitForEvent(wait_for_conditions=conditions_proto),
)
node_id = ack.node_id
branch_id = ack.branch_id
@@ -568,10 +589,11 @@ class DurableContext(Context):
ack = await self.durable_event_listener.send_event(
durable_task_external_id=self.step_run_id,
invocation_count=self.invocation_count,
kind=DurableTaskEventKind.DURABLE_TASK_TRIGGER_KIND_RUN,
payload=workflow._serialize_input(input),
workflow_name=workflow.config.name,
trigger_workflow_opts=options,
event=RunChildEvent(
workflow_name=workflow.config.name,
input=workflow._serialize_input(input, target="string"),
trigger_workflow_opts=options or TriggerWorkflowOptions(),
),
)
async with aio_durable_eviction_wait(
@@ -598,3 +620,68 @@ class DurableContext(Context):
@property
def invocation_count(self) -> int:
return self.action.durable_task_invocation_count or 1
async def aio_memo(
self,
fn: Callable[PMemo, Awaitable[TMemo]],
result_validator: type[TMemo],
/,
*args: PMemo.args,
**kwargs: PMemo.kwargs,
) -> TMemo:
"""
Memoize a function by storing its result in durable storage. This is useful for caching the results of expensive computations that you don't want to repeat on every workflow replay without needing to spawn a child workflow or set up an external cache. The function signature is intended to behave similarly to `asyncio.to_thread` or other similar uses of partially applied functions, where you pass in the function and its arguments separately.
Note that memoization is performed at the _task run_ level, meaning you cannot cache across tasks (whether they're part of the same workflow or otherwise).
:param fn: The function to compute the value to be memoized. This should be an async function that returns the value to be memoized.
:param result_validator: The type of the result to be memoized. This is used for validating the result when it's retrieved from durable storage and for properly serializing the result of the function call. This is required and generally we recommend using either a Pydantic model, a dataclass, or a TypedDict, but you can also use `dict` as an escape hatch.
:param *args: The arguments to pass to the function when computing the value to be memoized. These are used for computing the memoization key, so that different arguments will result in different cached values.
:param **kwargs: The keyword arguments to pass to the function when computing the value to be memoized. These are used for computing the memoization key, so that different keyword arguments will result in different cached values.
:return: The memoized value, either retrieved from durable storage or computed by calling the function.
:raises ValueError: If the durable event listener is not available.
"""
if self.durable_event_listener is None:
raise ValueError("Durable event listener is not available")
run_external_id = self.step_run_id
adapter = TypeAdapter(result_validator)
key = _compute_memo_key(self.step_run_id, *args, **kwargs)
ack = await self.durable_event_listener.send_event(
durable_task_external_id=run_external_id,
invocation_count=self.invocation_count,
event=MemoEvent(memo_key=key, result=None),
)
if ack.memo_already_existed and ack.memo_result_payload is None:
logger.warning(
"memo key found in durable storage but no data was returned. rerunning the function to recompute the value. "
)
if ack.memo_already_existed and ack.memo_result_payload is not None:
serialized_result = ack.memo_result_payload
result = adapter.validate_json(
serialized_result, context=HATCHET_PYDANTIC_SENTINEL
)
else:
result = await fn(*args, **kwargs)
serialized_result = adapter.dump_json(
result, context=HATCHET_PYDANTIC_SENTINEL
)
await self._ensure_stream_started()
await self.durable_event_listener.send_memo_completed_notification(
durable_task_external_id=run_external_id,
node_id=ack.node_id,
branch_id=ack.branch_id,
invocation_count=self.invocation_count,
memo_result_payload=serialized_result,
memo_key=key,
)
return result
File diff suppressed because one or more lines are too long
@@ -40,32 +40,38 @@ class DurableTaskResponseRegisterWorker(_message.Message):
def __init__(self, worker_id: _Optional[str] = ...) -> None: ...
class DurableTaskEventRequest(_message.Message):
__slots__ = ("invocation_count", "durable_task_external_id", "kind", "payload", "wait_for_conditions", "trigger_opts")
__slots__ = ("invocation_count", "durable_task_external_id", "kind", "payload", "wait_for_conditions", "trigger_opts", "memo_key")
INVOCATION_COUNT_FIELD_NUMBER: _ClassVar[int]
DURABLE_TASK_EXTERNAL_ID_FIELD_NUMBER: _ClassVar[int]
KIND_FIELD_NUMBER: _ClassVar[int]
PAYLOAD_FIELD_NUMBER: _ClassVar[int]
WAIT_FOR_CONDITIONS_FIELD_NUMBER: _ClassVar[int]
TRIGGER_OPTS_FIELD_NUMBER: _ClassVar[int]
MEMO_KEY_FIELD_NUMBER: _ClassVar[int]
invocation_count: int
durable_task_external_id: str
kind: DurableTaskEventKind
payload: bytes
wait_for_conditions: _condition_pb2.DurableEventListenerConditions
trigger_opts: _trigger_pb2.TriggerWorkflowRequest
def __init__(self, invocation_count: _Optional[int] = ..., durable_task_external_id: _Optional[str] = ..., kind: _Optional[_Union[DurableTaskEventKind, str]] = ..., payload: _Optional[bytes] = ..., wait_for_conditions: _Optional[_Union[_condition_pb2.DurableEventListenerConditions, _Mapping]] = ..., trigger_opts: _Optional[_Union[_trigger_pb2.TriggerWorkflowRequest, _Mapping]] = ...) -> None: ...
memo_key: bytes
def __init__(self, invocation_count: _Optional[int] = ..., durable_task_external_id: _Optional[str] = ..., kind: _Optional[_Union[DurableTaskEventKind, str]] = ..., payload: _Optional[bytes] = ..., wait_for_conditions: _Optional[_Union[_condition_pb2.DurableEventListenerConditions, _Mapping]] = ..., trigger_opts: _Optional[_Union[_trigger_pb2.TriggerWorkflowRequest, _Mapping]] = ..., memo_key: _Optional[bytes] = ...) -> None: ...
class DurableTaskEventAckResponse(_message.Message):
__slots__ = ("invocation_count", "durable_task_external_id", "branch_id", "node_id")
__slots__ = ("invocation_count", "durable_task_external_id", "branch_id", "node_id", "memo_already_existed", "memo_result_payload")
INVOCATION_COUNT_FIELD_NUMBER: _ClassVar[int]
DURABLE_TASK_EXTERNAL_ID_FIELD_NUMBER: _ClassVar[int]
BRANCH_ID_FIELD_NUMBER: _ClassVar[int]
NODE_ID_FIELD_NUMBER: _ClassVar[int]
MEMO_ALREADY_EXISTED_FIELD_NUMBER: _ClassVar[int]
MEMO_RESULT_PAYLOAD_FIELD_NUMBER: _ClassVar[int]
invocation_count: int
durable_task_external_id: str
branch_id: int
node_id: int
def __init__(self, invocation_count: _Optional[int] = ..., durable_task_external_id: _Optional[str] = ..., branch_id: _Optional[int] = ..., node_id: _Optional[int] = ...) -> None: ...
memo_already_existed: bool
memo_result_payload: bytes
def __init__(self, invocation_count: _Optional[int] = ..., durable_task_external_id: _Optional[str] = ..., branch_id: _Optional[int] = ..., node_id: _Optional[int] = ..., memo_already_existed: bool = ..., memo_result_payload: _Optional[bytes] = ...) -> None: ...
class DurableTaskEventLogEntryCompletedResponse(_message.Message):
__slots__ = ("durable_task_external_id", "invocation_count", "branch_id", "node_id", "payload")
@@ -117,17 +123,35 @@ class DurableTaskWorkerStatusRequest(_message.Message):
waiting_entries: _containers.RepeatedCompositeFieldContainer[DurableTaskAwaitedCompletedEntry]
def __init__(self, worker_id: _Optional[str] = ..., waiting_entries: _Optional[_Iterable[_Union[DurableTaskAwaitedCompletedEntry, _Mapping]]] = ...) -> None: ...
class DurableTaskCompleteMemoRequest(_message.Message):
__slots__ = ("durable_task_external_id", "invocation_count", "branch_id", "node_id", "payload", "memo_key")
DURABLE_TASK_EXTERNAL_ID_FIELD_NUMBER: _ClassVar[int]
INVOCATION_COUNT_FIELD_NUMBER: _ClassVar[int]
BRANCH_ID_FIELD_NUMBER: _ClassVar[int]
NODE_ID_FIELD_NUMBER: _ClassVar[int]
PAYLOAD_FIELD_NUMBER: _ClassVar[int]
MEMO_KEY_FIELD_NUMBER: _ClassVar[int]
durable_task_external_id: str
invocation_count: int
branch_id: int
node_id: int
payload: bytes
memo_key: bytes
def __init__(self, durable_task_external_id: _Optional[str] = ..., invocation_count: _Optional[int] = ..., branch_id: _Optional[int] = ..., node_id: _Optional[int] = ..., payload: _Optional[bytes] = ..., memo_key: _Optional[bytes] = ...) -> None: ...
class DurableTaskRequest(_message.Message):
__slots__ = ("register_worker", "event", "evict_invocation", "worker_status")
__slots__ = ("register_worker", "event", "evict_invocation", "worker_status", "complete_memo")
REGISTER_WORKER_FIELD_NUMBER: _ClassVar[int]
EVENT_FIELD_NUMBER: _ClassVar[int]
EVICT_INVOCATION_FIELD_NUMBER: _ClassVar[int]
WORKER_STATUS_FIELD_NUMBER: _ClassVar[int]
COMPLETE_MEMO_FIELD_NUMBER: _ClassVar[int]
register_worker: DurableTaskRequestRegisterWorker
event: DurableTaskEventRequest
evict_invocation: DurableTaskEvictInvocationRequest
worker_status: DurableTaskWorkerStatusRequest
def __init__(self, register_worker: _Optional[_Union[DurableTaskRequestRegisterWorker, _Mapping]] = ..., event: _Optional[_Union[DurableTaskEventRequest, _Mapping]] = ..., evict_invocation: _Optional[_Union[DurableTaskEvictInvocationRequest, _Mapping]] = ..., worker_status: _Optional[_Union[DurableTaskWorkerStatusRequest, _Mapping]] = ...) -> None: ...
complete_memo: DurableTaskCompleteMemoRequest
def __init__(self, register_worker: _Optional[_Union[DurableTaskRequestRegisterWorker, _Mapping]] = ..., event: _Optional[_Union[DurableTaskEventRequest, _Mapping]] = ..., evict_invocation: _Optional[_Union[DurableTaskEvictInvocationRequest, _Mapping]] = ..., worker_status: _Optional[_Union[DurableTaskWorkerStatusRequest, _Mapping]] = ..., complete_memo: _Optional[_Union[DurableTaskCompleteMemoRequest, _Mapping]] = ...) -> None: ...
class DurableTaskErrorResponse(_message.Message):
__slots__ = ("durable_task_external_id", "invocation_count", "branch_id", "node_id", "error_type", "error_message")
+24 -24
View File
@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 2.0.0 and should not be changed by hand.
[[package]]
name = "aiohappyeyeballs"
@@ -153,7 +153,7 @@ propcache = ">=0.2.0"
yarl = ">=1.17.0,<2.0"
[package.extras]
speedups = ["Brotli (>=1.2) ; platform_python_implementation == \"CPython\"", "aiodns (>=3.3.0)", "backports.zstd ; platform_python_implementation == \"CPython\" and python_version < \"3.14\"", "brotlicffi (>=1.2) ; platform_python_implementation != \"CPython\""]
speedups = ["Brotli (>=1.2)", "aiodns (>=3.3.0)", "backports.zstd", "brotlicffi (>=1.2)"]
[[package]]
name = "aiosignal"
@@ -201,7 +201,7 @@ idna = ">=2.8"
typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""}
[package.extras]
trio = ["trio (>=0.31.0) ; python_version < \"3.10\"", "trio (>=0.32.0) ; python_version >= \"3.10\""]
trio = ["trio (>=0.31.0)", "trio (>=0.32.0)"]
[[package]]
name = "async-timeout"
@@ -210,7 +210,7 @@ description = "Timeout context manager for asyncio programs"
optional = false
python-versions = ">=3.8"
groups = ["main"]
markers = "python_version == \"3.10\""
markers = "python_version < \"3.11\""
files = [
{file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"},
{file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"},
@@ -235,7 +235,7 @@ description = "Backport of asyncio.Runner, a context manager that controls event
optional = false
python-versions = "<3.11,>=3.8"
groups = ["test"]
markers = "python_version == \"3.10\""
markers = "python_version < \"3.11\""
files = [
{file = "backports_asyncio_runner-1.2.0-py3-none-any.whl", hash = "sha256:0da0a936a8aeb554eccb426dc55af3ba63bcdc69fa1a600b5bb305413a4477b5"},
{file = "backports_asyncio_runner-1.2.0.tar.gz", hash = "sha256:a5aa7b2b7d8f8bfcaa2b57313f70792df84e32a2a746f585213373f900b42162"},
@@ -520,7 +520,7 @@ files = [
]
[package.extras]
dev = ["docstring-parser[docs]", "docstring-parser[test]", "pre-commit (>=2.16.0) ; python_version >= \"3.9\""]
dev = ["docstring-parser[docs]", "docstring-parser[test]", "pre-commit (>=2.16.0)"]
docs = ["pydoctor (>=25.4.0)"]
test = ["pytest"]
@@ -531,7 +531,7 @@ description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
groups = ["docs", "test"]
markers = "python_version == \"3.10\""
markers = "python_version < \"3.11\""
files = [
{file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"},
{file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"},
@@ -1009,7 +1009,7 @@ httpcore = "==1.*"
idna = "*"
[package.extras]
brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""]
brotli = ["brotli", "brotlicffi"]
cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
@@ -1047,13 +1047,13 @@ files = [
zipp = ">=3.20"
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
enabler = ["pytest-enabler (>=3.4)"]
perf = ["ipython"]
test = ["flufl.flake8", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
type = ["mypy (<1.19) ; platform_python_implementation == \"PyPy\"", "pytest-mypy (>=1.0.1)"]
type = ["mypy (<1.19)", "pytest-mypy (>=1.0.1)"]
[[package]]
name = "iniconfig"
@@ -1470,7 +1470,7 @@ watchdog = ">=2.0"
[package.extras]
i18n = ["babel (>=2.9.0)"]
min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4) ; platform_system == \"Windows\"", "ghp-import (==1.0)", "importlib-metadata (==4.4) ; python_version < \"3.10\"", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"]
min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"]
[[package]]
name = "mkdocs-autorefs"
@@ -2282,12 +2282,12 @@ typing-extensions = {version = ">=4.6", markers = "python_version < \"3.13\""}
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
[package.extras]
binary = ["psycopg-binary (==3.3.3) ; implementation_name != \"pypy\""]
c = ["psycopg-c (==3.3.3) ; implementation_name != \"pypy\""]
binary = ["psycopg-binary (==3.3.3)"]
c = ["psycopg-c (==3.3.3)"]
dev = ["ast-comments (>=1.1.2)", "black (>=26.1.0)", "codespell (>=2.2)", "cython-lint (>=0.16)", "dnspython (>=2.1)", "flake8 (>=4.0)", "isort-psycopg", "isort[colors] (>=6.0)", "mypy (>=1.19.0)", "pre-commit (>=4.0.1)", "types-setuptools (>=57.4)", "types-shapely (>=2.0)", "wheel (>=0.37)"]
docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"]
pool = ["psycopg-pool"]
test = ["anyio (>=4.0)", "mypy (>=1.19.0) ; implementation_name != \"pypy\"", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"]
test = ["anyio (>=4.0)", "mypy (>=1.19.0)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"]
[[package]]
name = "psycopg-pool"
@@ -2327,7 +2327,7 @@ typing-inspection = ">=0.4.2"
[package.extras]
email = ["email-validator (>=2.0.0)"]
timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""]
timezone = ["tzdata"]
[[package]]
name = "pydantic-core"
@@ -2890,13 +2890,13 @@ files = [
]
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.13.0) ; sys_platform != \"cygwin\""]
core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.13.0)"]
core = ["importlib_metadata (>=6)", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"]
cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"]
enabler = ["pytest-enabler (>=2.2)"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.18.*)", "pytest-mypy"]
test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"]
type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (==1.18.*)", "pytest-mypy"]
[[package]]
name = "six"
@@ -2975,7 +2975,7 @@ description = "A lil' TOML parser"
optional = false
python-versions = ">=3.8"
groups = ["docs", "lint", "test"]
markers = "python_version == \"3.10\""
markers = "python_version < \"3.11\""
files = [
{file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"},
{file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"},
@@ -3194,10 +3194,10 @@ files = [
]
[package.extras]
brotli = ["brotli (>=1.2.0) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=1.2.0.0) ; platform_python_implementation != \"CPython\""]
brotli = ["brotli (>=1.2.0)", "brotlicffi (>=1.2.0.0)"]
h2 = ["h2 (>=4,<5)"]
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""]
zstd = ["backports-zstd (>=1.0.0)"]
[[package]]
name = "uvicorn"
@@ -3217,7 +3217,7 @@ h11 = ">=0.8"
typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
[package.extras]
standard = ["colorama (>=0.4) ; sys_platform == \"win32\"", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1) ; sys_platform != \"win32\" and sys_platform != \"cygwin\" and platform_python_implementation != \"PyPy\"", "watchfiles (>=0.13)", "websockets (>=10.4)"]
standard = ["colorama (>=0.4)", "httptools (>=0.6.3)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
[[package]]
name = "watchdog"
@@ -3513,7 +3513,7 @@ files = [
]
[package.extras]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\""]
check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)"]
cover = ["pytest-cov"]
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
enabler = ["pytest-enabler (>=2.2)"]