From 5a14946349ac46f5643f3a3034bd4cdab75fb55e Mon Sep 17 00:00:00 2001 From: Yunchu Wang <12449837+YunchuWang@users.noreply.github.com> Date: Fri, 1 May 2026 09:54:11 -0700 Subject: [PATCH 1/2] Remove durabletask-protobuf submodule and vendor the proto file Mirrors microsoft/durabletask-java#207 for the Go SDK. * Removes the submodules/durabletask-protobuf git submodule. * Vendors orchestrator_service.proto under internal/durabletask-protobuf/protos/ at the previously pinned commit (4207e1d) so the existing committed .pb.go files remain in sync and CI builds stay deterministic. * Adds internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH to track the upstream source commit. * Adds internal/durabletask-protobuf/update-proto.sh, a helper script that resolves the commit SHA on a branch, downloads orchestrator_service.proto at that exact SHA, and writes the SHA to PROTO_SOURCE_COMMIT_HASH. * Adds internal/durabletask-protobuf/README.md documenting the workflow. * Updates the PR validation workflow to drop `submodules: true` and point the `protoc -I` path at the vendored location. * Updates README.md and CHANGELOG.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/pr-validation.yml | 3 +- .gitmodules | 4 - CHANGELOG.md | 6 + README.md | 10 +- .../PROTO_SOURCE_COMMIT_HASH | 1 + internal/durabletask-protobuf/README.md | 29 + .../protos/orchestrator_service.proto | 617 ++++++++++++++++++ internal/durabletask-protobuf/update-proto.sh | 57 ++ submodules/durabletask-protobuf | 1 - 9 files changed, 717 insertions(+), 11 deletions(-) delete mode 100644 .gitmodules create mode 100644 internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH create mode 100644 internal/durabletask-protobuf/README.md create mode 100644 internal/durabletask-protobuf/protos/orchestrator_service.proto create mode 100755 internal/durabletask-protobuf/update-proto.sh delete mode 160000 submodules/durabletask-protobuf diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index b57ec8d..a57873e 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -53,7 +53,6 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 1 - submodules: true - name: Setup Go environment uses: actions/setup-go@v5 @@ -74,7 +73,7 @@ jobs: go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@$PROTOC_GEN_GO_GRPC - name: Generate grpc code - run: protoc --go_out=. --go-grpc_out=. -I ./submodules/durabletask-protobuf/protos orchestrator_service.proto + run: protoc --go_out=. --go-grpc_out=. -I ./internal/durabletask-protobuf/protos orchestrator_service.proto - name: Run go vet run: go vet ./... diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e0a2ae7..0000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "submodules/durabletask-protobuf"] - path = submodules/durabletask-protobuf - url = https://github.com/microsoft/durabletask-protobuf - branch = main diff --git a/CHANGELOG.md b/CHANGELOG.md index a24df9b..bc252b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Removed the `submodules/durabletask-protobuf` git submodule. The `orchestrator_service.proto` file is now vendored under `internal/durabletask-protobuf/protos/`, with the source commit hash tracked in `internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH` and a helper script (`internal/durabletask-protobuf/update-proto.sh`) for refreshing the proto from upstream. + ## [v0.6.0] - 2025-02-05 ### Added diff --git a/README.md b/README.md index 9cd8e45..74aea2b 100644 --- a/README.md +++ b/README.md @@ -247,23 +247,25 @@ Note that each orchestration is represented as a single span with activities, ti ## Cloning this repository -This repository contains submodules. Be sure to clone it with the option to include submodules. Otherwise you will not be able to generate the protobuf code. +Clone the repository as you normally would: ```bash -git clone --recurse-submodules https://github.com/microsoft/durabletask-go +git clone https://github.com/microsoft/durabletask-go ``` +The protocol buffer definitions used to generate the gRPC bindings are vendored under [`internal/durabletask-protobuf/protos`](./internal/durabletask-protobuf/protos). See [`internal/durabletask-protobuf/README.md`](./internal/durabletask-protobuf/README.md) for details on how to refresh them from the upstream [microsoft/durabletask-protobuf](https://github.com/microsoft/durabletask-protobuf) repository. + ## Building the project This project requires go v1.19.x or greater. You can build a standalone executable by simply running `go build` at the project root. ### Generating protobuf -Use the following command to regenerate the protobuf from the submodule. Use this whenever updating the submodule reference. +Use the following command to regenerate the protobuf bindings from the vendored proto file. Use this whenever updating the proto file under [`internal/durabletask-protobuf/protos`](./internal/durabletask-protobuf/protos). ```bash # NOTE: assumes the .proto file defines: option go_package = "/internal/protos" -protoc --go_out=. --go-grpc_out=. -I submodules/durabletask-protobuf/protos orchestrator_service.proto +protoc --go_out=. --go-grpc_out=. -I internal/durabletask-protobuf/protos orchestrator_service.proto ``` ### Generating mocks for testing diff --git a/internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH b/internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH new file mode 100644 index 0000000..d9d80bf --- /dev/null +++ b/internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH @@ -0,0 +1 @@ +4207e1dbd14cedc268f69c3befee60fcaad19367 \ No newline at end of file diff --git a/internal/durabletask-protobuf/README.md b/internal/durabletask-protobuf/README.md new file mode 100644 index 0000000..28590e7 --- /dev/null +++ b/internal/durabletask-protobuf/README.md @@ -0,0 +1,29 @@ +# Durable Task Protobuf Files + +This directory contains the protocol buffer definitions used by the Durable Task Framework Go SDK. The files in this directory are vendored from the [microsoft/durabletask-protobuf](https://github.com/microsoft/durabletask-protobuf) repository. + +## Directory Structure + +- `protos/` - Contains the vendored proto files +- `PROTO_SOURCE_COMMIT_HASH` - Contains the commit hash of the upstream `microsoft/durabletask-protobuf` repository that the proto files were last synced from +- `update-proto.sh` - Helper script to refresh the vendored proto file and commit hash from upstream + +## Updating the proto files + +Run the helper script from the repository root to download the latest `orchestrator_service.proto` from upstream and update `PROTO_SOURCE_COMMIT_HASH`: + +```bash +# Update from the default branch (main) +./internal/durabletask-protobuf/update-proto.sh + +# Update from a specific branch +./internal/durabletask-protobuf/update-proto.sh +``` + +After running the script, regenerate the Go gRPC bindings so that the committed `internal/protos/*.pb.go` files match the updated `.proto`: + +```bash +protoc --go_out=. --go-grpc_out=. -I ./internal/durabletask-protobuf/protos orchestrator_service.proto +``` + +Commit both the updated proto file, `PROTO_SOURCE_COMMIT_HASH`, and the regenerated `.pb.go` files together. diff --git a/internal/durabletask-protobuf/protos/orchestrator_service.proto b/internal/durabletask-protobuf/protos/orchestrator_service.proto new file mode 100644 index 0000000..2ca3755 --- /dev/null +++ b/internal/durabletask-protobuf/protos/orchestrator_service.proto @@ -0,0 +1,617 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +syntax = "proto3"; + +option csharp_namespace = "Microsoft.DurableTask.Protobuf"; +option java_package = "com.microsoft.durabletask.implementation.protobuf"; +option go_package = "/internal/protos"; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/empty.proto"; + +message OrchestrationInstance { + string instanceId = 1; + google.protobuf.StringValue executionId = 2; +} + +message ActivityRequest { + string name = 1; + google.protobuf.StringValue version = 2; + google.protobuf.StringValue input = 3; + OrchestrationInstance orchestrationInstance = 4; + int32 taskId = 5; +} + +message ActivityResponse { + string instanceId = 1; + int32 taskId = 2; + google.protobuf.StringValue result = 3; + TaskFailureDetails failureDetails = 4; +} + +message TaskFailureDetails { + string errorType = 1; + string errorMessage = 2; + google.protobuf.StringValue stackTrace = 3; + TaskFailureDetails innerFailure = 4; + bool isNonRetriable = 5; +} + +enum OrchestrationStatus { + ORCHESTRATION_STATUS_RUNNING = 0; + ORCHESTRATION_STATUS_COMPLETED = 1; + ORCHESTRATION_STATUS_CONTINUED_AS_NEW = 2; + ORCHESTRATION_STATUS_FAILED = 3; + ORCHESTRATION_STATUS_CANCELED = 4; + ORCHESTRATION_STATUS_TERMINATED = 5; + ORCHESTRATION_STATUS_PENDING = 6; + ORCHESTRATION_STATUS_SUSPENDED = 7; +} + +message ParentInstanceInfo { + int32 taskScheduledId = 1; + google.protobuf.StringValue name = 2; + google.protobuf.StringValue version = 3; + OrchestrationInstance orchestrationInstance = 4; +} + +message TraceContext { + string traceParent = 1; + string spanID = 2 [deprecated=true]; + google.protobuf.StringValue traceState = 3; +} + +message ExecutionStartedEvent { + string name = 1; + google.protobuf.StringValue version = 2; + google.protobuf.StringValue input = 3; + OrchestrationInstance orchestrationInstance = 4; + ParentInstanceInfo parentInstance = 5; + google.protobuf.Timestamp scheduledStartTimestamp = 6; + TraceContext parentTraceContext = 7; + google.protobuf.StringValue orchestrationSpanID = 8; +} + +message ExecutionCompletedEvent { + OrchestrationStatus orchestrationStatus = 1; + google.protobuf.StringValue result = 2; + TaskFailureDetails failureDetails = 3; +} + +message ExecutionTerminatedEvent { + google.protobuf.StringValue input = 1; + bool recurse = 2; +} + +message TaskScheduledEvent { + string name = 1; + google.protobuf.StringValue version = 2; + google.protobuf.StringValue input = 3; + TraceContext parentTraceContext = 4; +} + +message TaskCompletedEvent { + int32 taskScheduledId = 1; + google.protobuf.StringValue result = 2; +} + +message TaskFailedEvent { + int32 taskScheduledId = 1; + TaskFailureDetails failureDetails = 2; +} + +message SubOrchestrationInstanceCreatedEvent { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue version = 3; + google.protobuf.StringValue input = 4; + TraceContext parentTraceContext = 5; +} + +message SubOrchestrationInstanceCompletedEvent { + int32 taskScheduledId = 1; + google.protobuf.StringValue result = 2; +} + +message SubOrchestrationInstanceFailedEvent { + int32 taskScheduledId = 1; + TaskFailureDetails failureDetails = 2; +} + +message TimerCreatedEvent { + google.protobuf.Timestamp fireAt = 1; +} + +message TimerFiredEvent { + google.protobuf.Timestamp fireAt = 1; + int32 timerId = 2; +} + +message OrchestratorStartedEvent { + // No payload data +} + +message OrchestratorCompletedEvent { + // No payload data +} + +message EventSentEvent { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue input = 3; +} + +message EventRaisedEvent { + string name = 1; + google.protobuf.StringValue input = 2; +} + +message GenericEvent { + google.protobuf.StringValue data = 1; +} + +message HistoryStateEvent { + OrchestrationState orchestrationState = 1; +} + +message ContinueAsNewEvent { + google.protobuf.StringValue input = 1; +} + +message ExecutionSuspendedEvent { + google.protobuf.StringValue input = 1; +} + +message ExecutionResumedEvent { + google.protobuf.StringValue input = 1; +} + +message HistoryEvent { + int32 eventId = 1; + google.protobuf.Timestamp timestamp = 2; + oneof eventType { + ExecutionStartedEvent executionStarted = 3; + ExecutionCompletedEvent executionCompleted = 4; + ExecutionTerminatedEvent executionTerminated = 5; + TaskScheduledEvent taskScheduled = 6; + TaskCompletedEvent taskCompleted = 7; + TaskFailedEvent taskFailed = 8; + SubOrchestrationInstanceCreatedEvent subOrchestrationInstanceCreated = 9; + SubOrchestrationInstanceCompletedEvent subOrchestrationInstanceCompleted = 10; + SubOrchestrationInstanceFailedEvent subOrchestrationInstanceFailed = 11; + TimerCreatedEvent timerCreated = 12; + TimerFiredEvent timerFired = 13; + OrchestratorStartedEvent orchestratorStarted = 14; + OrchestratorCompletedEvent orchestratorCompleted = 15; + EventSentEvent eventSent = 16; + EventRaisedEvent eventRaised = 17; + GenericEvent genericEvent = 18; + HistoryStateEvent historyState = 19; + ContinueAsNewEvent continueAsNew = 20; + ExecutionSuspendedEvent executionSuspended = 21; + ExecutionResumedEvent executionResumed = 22; + } +} + +message ScheduleTaskAction { + string name = 1; + google.protobuf.StringValue version = 2; + google.protobuf.StringValue input = 3; +} + +message CreateSubOrchestrationAction { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue version = 3; + google.protobuf.StringValue input = 4; +} + +message CreateTimerAction { + google.protobuf.Timestamp fireAt = 1; +} + +message SendEventAction { + OrchestrationInstance instance = 1; + string name = 2; + google.protobuf.StringValue data = 3; +} + +message CompleteOrchestrationAction { + OrchestrationStatus orchestrationStatus = 1; + google.protobuf.StringValue result = 2; + google.protobuf.StringValue details = 3; + google.protobuf.StringValue newVersion = 4; + repeated HistoryEvent carryoverEvents = 5; + TaskFailureDetails failureDetails = 6; +} + +message TerminateOrchestrationAction { + string instanceId = 1; + google.protobuf.StringValue reason = 2; + bool recurse = 3; +} + +message OrchestratorAction { + int32 id = 1; + oneof orchestratorActionType { + ScheduleTaskAction scheduleTask = 2; + CreateSubOrchestrationAction createSubOrchestration = 3; + CreateTimerAction createTimer = 4; + SendEventAction sendEvent = 5; + CompleteOrchestrationAction completeOrchestration = 6; + TerminateOrchestrationAction terminateOrchestration = 7; + } +} + +message OrchestratorRequest { + string instanceId = 1; + google.protobuf.StringValue executionId = 2; + repeated HistoryEvent pastEvents = 3; + repeated HistoryEvent newEvents = 4; + OrchestratorEntityParameters entityParameters = 5; +} + +message OrchestratorResponse { + string instanceId = 1; + repeated OrchestratorAction actions = 2; + google.protobuf.StringValue customStatus = 3; +} + +message CreateInstanceRequest { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue version = 3; + google.protobuf.StringValue input = 4; + google.protobuf.Timestamp scheduledStartTimestamp = 5; + OrchestrationIdReusePolicy orchestrationIdReusePolicy = 6; +} + +message OrchestrationIdReusePolicy { + repeated OrchestrationStatus operationStatus = 1; + CreateOrchestrationAction action = 2; +} + +enum CreateOrchestrationAction { + ERROR = 0; + IGNORE = 1; + TERMINATE = 2; +} + +message CreateInstanceResponse { + string instanceId = 1; +} + +message GetInstanceRequest { + string instanceId = 1; + bool getInputsAndOutputs = 2; +} + +message GetInstanceResponse { + bool exists = 1; + OrchestrationState orchestrationState = 2; +} + +message RewindInstanceRequest { + string instanceId = 1; + google.protobuf.StringValue reason = 2; +} + +message RewindInstanceResponse { + // Empty for now. Using explicit type incase we want to add content later. +} + +message OrchestrationState { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue version = 3; + OrchestrationStatus orchestrationStatus = 4; + google.protobuf.Timestamp scheduledStartTimestamp = 5; + google.protobuf.Timestamp createdTimestamp = 6; + google.protobuf.Timestamp lastUpdatedTimestamp = 7; + google.protobuf.StringValue input = 8; + google.protobuf.StringValue output = 9; + google.protobuf.StringValue customStatus = 10; + TaskFailureDetails failureDetails = 11; +} + +message RaiseEventRequest { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue input = 3; +} + +message RaiseEventResponse { + // No payload +} + +message TerminateRequest { + string instanceId = 1; + google.protobuf.StringValue output = 2; + bool recursive = 3; +} + +message TerminateResponse { + // No payload +} + +message SuspendRequest { + string instanceId = 1; + google.protobuf.StringValue reason = 2; +} + +message SuspendResponse { + // No payload +} + +message ResumeRequest { + string instanceId = 1; + google.protobuf.StringValue reason = 2; +} + +message ResumeResponse { + // No payload +} + +message QueryInstancesRequest { + InstanceQuery query = 1; +} + +message InstanceQuery{ + repeated OrchestrationStatus runtimeStatus = 1; + google.protobuf.Timestamp createdTimeFrom = 2; + google.protobuf.Timestamp createdTimeTo = 3; + repeated google.protobuf.StringValue taskHubNames = 4; + int32 maxInstanceCount = 5; + google.protobuf.StringValue continuationToken = 6; + google.protobuf.StringValue instanceIdPrefix = 7; + bool fetchInputsAndOutputs = 8; +} + +message QueryInstancesResponse { + repeated OrchestrationState orchestrationState = 1; + google.protobuf.StringValue continuationToken = 2; +} + +message PurgeInstancesRequest { + oneof request { + string instanceId = 1; + PurgeInstanceFilter purgeInstanceFilter = 2; + } + bool recursive = 3; +} + +message PurgeInstanceFilter { + google.protobuf.Timestamp createdTimeFrom = 1; + google.protobuf.Timestamp createdTimeTo = 2; + repeated OrchestrationStatus runtimeStatus = 3; +} + +message PurgeInstancesResponse { + int32 deletedInstanceCount = 1; +} + +message CreateTaskHubRequest { + bool recreateIfExists = 1; +} + +message CreateTaskHubResponse { + //no playload +} + +message DeleteTaskHubRequest { + //no playload +} + +message DeleteTaskHubResponse { + //no playload +} + +message SignalEntityRequest { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue input = 3; + string requestId = 4; + google.protobuf.Timestamp scheduledTime = 5; +} + +message SignalEntityResponse { + // no payload +} + +message GetEntityRequest +{ + string instanceId = 1; + bool includeState = 2; +} + +message GetEntityResponse +{ + bool exists = 1; + EntityMetadata entity = 2; +} + +message EntityQuery +{ + google.protobuf.StringValue instanceIdStartsWith = 1; + google.protobuf.Timestamp lastModifiedFrom = 2; + google.protobuf.Timestamp lastModifiedTo = 3; + bool includeState = 4; + bool includeTransient = 5; + google.protobuf.Int32Value pageSize = 6; + google.protobuf.StringValue continuationToken = 7; +} + +message QueryEntitiesRequest +{ + EntityQuery query = 1; +} + +message QueryEntitiesResponse +{ + repeated EntityMetadata entities = 1; + google.protobuf.StringValue continuationToken = 2; +} + +message EntityMetadata +{ + string instanceId = 1; + google.protobuf.Timestamp lastModifiedTime = 2; + int32 backlogQueueSize = 3; + google.protobuf.StringValue lockedBy = 4; + google.protobuf.StringValue serializedState = 5; +} + +message CleanEntityStorageRequest +{ + google.protobuf.StringValue continuationToken = 1; + bool removeEmptyEntities = 2; + bool releaseOrphanedLocks = 3; +} + +message CleanEntityStorageResponse +{ + google.protobuf.StringValue continuationToken = 1; + int32 emptyEntitiesRemoved = 2; + int32 orphanedLocksReleased = 3; +} + +message OrchestratorEntityParameters +{ + google.protobuf.Duration entityMessageReorderWindow = 1; +} + +message EntityBatchRequest { + string instanceId = 1; + google.protobuf.StringValue entityState = 2; + repeated OperationRequest operations = 3; +} + +message EntityBatchResult { + repeated OperationResult results = 1; + repeated OperationAction actions = 2; + google.protobuf.StringValue entityState = 3; + TaskFailureDetails failureDetails = 4; +} + +message OperationRequest { + string operation = 1; + string requestId = 2; + google.protobuf.StringValue input = 3; +} + +message OperationResult { + oneof resultType { + OperationResultSuccess success = 1; + OperationResultFailure failure = 2; + } +} + +message OperationResultSuccess { + google.protobuf.StringValue result = 1; +} + +message OperationResultFailure { + TaskFailureDetails failureDetails = 1; +} + +message OperationAction { + int32 id = 1; + oneof operationActionType { + SendSignalAction sendSignal = 2; + StartNewOrchestrationAction startNewOrchestration = 3; + } +} + +message SendSignalAction { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue input = 3; + google.protobuf.Timestamp scheduledTime = 4; +} + +message StartNewOrchestrationAction { + string instanceId = 1; + string name = 2; + google.protobuf.StringValue version = 3; + google.protobuf.StringValue input = 4; + google.protobuf.Timestamp scheduledTime = 5; +} + +service TaskHubSidecarService { + // Sends a hello request to the sidecar service. + rpc Hello(google.protobuf.Empty) returns (google.protobuf.Empty); + + // Starts a new orchestration instance. + rpc StartInstance(CreateInstanceRequest) returns (CreateInstanceResponse); + + // Gets the status of an existing orchestration instance. + rpc GetInstance(GetInstanceRequest) returns (GetInstanceResponse); + + // Rewinds an orchestration instance to last known good state and replays from there. + rpc RewindInstance(RewindInstanceRequest) returns (RewindInstanceResponse); + + // Waits for an orchestration instance to reach a running or completion state. + rpc WaitForInstanceStart(GetInstanceRequest) returns (GetInstanceResponse); + + // Waits for an orchestration instance to reach a completion state (completed, failed, terminated, etc.). + rpc WaitForInstanceCompletion(GetInstanceRequest) returns (GetInstanceResponse); + + // Raises an event to a running orchestration instance. + rpc RaiseEvent(RaiseEventRequest) returns (RaiseEventResponse); + + // Terminates a running orchestration instance. + rpc TerminateInstance(TerminateRequest) returns (TerminateResponse); + + // Suspends a running orchestration instance. + rpc SuspendInstance(SuspendRequest) returns (SuspendResponse); + + // Resumes a suspended orchestration instance. + rpc ResumeInstance(ResumeRequest) returns (ResumeResponse); + + // rpc DeleteInstance(DeleteInstanceRequest) returns (DeleteInstanceResponse); + + rpc QueryInstances(QueryInstancesRequest) returns (QueryInstancesResponse); + rpc PurgeInstances(PurgeInstancesRequest) returns (PurgeInstancesResponse); + + rpc GetWorkItems(GetWorkItemsRequest) returns (stream WorkItem); + rpc CompleteActivityTask(ActivityResponse) returns (CompleteTaskResponse); + rpc CompleteOrchestratorTask(OrchestratorResponse) returns (CompleteTaskResponse); + rpc CompleteEntityTask(EntityBatchResult) returns (CompleteTaskResponse); + + // Deletes and Creates the necessary resources for the orchestration service and the instance store + rpc CreateTaskHub(CreateTaskHubRequest) returns (CreateTaskHubResponse); + + // Deletes the resources for the orchestration service and optionally the instance store + rpc DeleteTaskHub(DeleteTaskHubRequest) returns (DeleteTaskHubResponse); + + // sends a signal to an entity + rpc SignalEntity(SignalEntityRequest) returns (SignalEntityResponse); + + // get information about a specific entity + rpc GetEntity(GetEntityRequest) returns (GetEntityResponse); + + // query entities + rpc QueryEntities(QueryEntitiesRequest) returns (QueryEntitiesResponse); + + // clean entity storage + rpc CleanEntityStorage(CleanEntityStorageRequest) returns (CleanEntityStorageResponse); +} + +message GetWorkItemsRequest { + // No parameters currently +} + +message WorkItem { + oneof request { + OrchestratorRequest orchestratorRequest = 1; + ActivityRequest activityRequest = 2; + EntityBatchRequest entityRequest = 3; + } +} + +message CompleteTaskResponse { + // No payload +} \ No newline at end of file diff --git a/internal/durabletask-protobuf/update-proto.sh b/internal/durabletask-protobuf/update-proto.sh new file mode 100755 index 0000000..72f89e2 --- /dev/null +++ b/internal/durabletask-protobuf/update-proto.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# Downloads the latest orchestrator_service.proto from the +# microsoft/durabletask-protobuf repository and writes the source +# commit hash to PROTO_SOURCE_COMMIT_HASH. +# +# Usage: +# ./internal/durabletask-protobuf/update-proto.sh [branch] +# +# If [branch] is omitted, "main" is used. + +set -euo pipefail + +BRANCH="${1:-main}" +REPO="microsoft/durabletask-protobuf" +PROTO_PATH="protos/orchestrator_service.proto" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROTO_DIR="${SCRIPT_DIR}/protos" +HASH_FILE="${SCRIPT_DIR}/PROTO_SOURCE_COMMIT_HASH" + +mkdir -p "${PROTO_DIR}" + +CURL_AUTH=() +if [[ -n "${GITHUB_TOKEN:-}" ]]; then + CURL_AUTH=(-H "Authorization: Bearer ${GITHUB_TOKEN}") +fi + +echo "Resolving latest commit for ${PROTO_PATH} on ${REPO}@${BRANCH}..." +COMMIT_API_URL="https://api.github.com/repos/${REPO}/commits?path=${PROTO_PATH}&sha=${BRANCH}&per_page=1" +COMMIT_RESPONSE=$(curl -fsSL \ + "${CURL_AUTH[@]}" \ + -H "Accept: application/vnd.github.v3+json" \ + "${COMMIT_API_URL}") + +# Extract the first "sha": "" value from the JSON response. +COMMIT_HASH=$(printf '%s' "${COMMIT_RESPONSE}" \ + | grep -o '"sha"[[:space:]]*:[[:space:]]*"[^"]*"' \ + | head -n 1 \ + | sed -E 's/.*"sha"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/') + +if [[ -z "${COMMIT_HASH}" ]]; then + echo "Failed to resolve commit hash from ${COMMIT_API_URL}" >&2 + exit 1 +fi + +echo "Downloading ${PROTO_PATH}@${COMMIT_HASH}..." +curl -fsSL \ + "https://raw.githubusercontent.com/${REPO}/${COMMIT_HASH}/${PROTO_PATH}" \ + -o "${PROTO_DIR}/orchestrator_service.proto" + +echo "${COMMIT_HASH}" > "${HASH_FILE}" + +echo "Updated ${PROTO_DIR}/orchestrator_service.proto" +echo "Recorded commit hash ${COMMIT_HASH} in ${HASH_FILE}" +echo +echo "Next step: regenerate the Go bindings:" +echo " protoc --go_out=. --go-grpc_out=. -I ./internal/durabletask-protobuf/protos orchestrator_service.proto" diff --git a/submodules/durabletask-protobuf b/submodules/durabletask-protobuf deleted file mode 160000 index 4207e1d..0000000 --- a/submodules/durabletask-protobuf +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4207e1dbd14cedc268f69c3befee60fcaad19367 From 86e76d76f2939604a6a23c8e676c5c2ec52067bf Mon Sep 17 00:00:00 2001 From: YunchuWang <223556219+Copilot@users.noreply.github.com> Date: Fri, 1 May 2026 13:40:24 -0700 Subject: [PATCH 2/2] Address PR review feedback - Rename internal/durabletask-protobuf -> vendored/durabletask-protobuf (cgillum) - Expand PROTO_SOURCE_COMMIT_HASH to include Source/Branch/Commit/URL (cgillum) - Replace 'grep -o | head | sed' pipeline in update-proto.sh with single 'sed -nE ...p | head -n 1', so it doesn't abort silently under 'set -euo pipefail' when the pattern is absent (Copilot bot) - update-proto.sh now accepts any ref (branch/tag/SHA) and dumps the API response when no commit can be resolved - Add .gitattributes (*.sh text eol=lf) so Windows clones don't reintroduce CRLF into update-proto.sh Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .gitattributes | 1 + .github/workflows/pr-validation.yml | 2 +- CHANGELOG.md | 2 +- README.md | 6 +-- .../PROTO_SOURCE_COMMIT_HASH | 1 - .../PROTO_SOURCE_COMMIT_HASH | 4 ++ .../durabletask-protobuf/README.md | 12 +++--- .../protos/orchestrator_service.proto | 0 .../durabletask-protobuf/update-proto.sh | 38 ++++++++++++------- 9 files changed, 41 insertions(+), 25 deletions(-) create mode 100644 .gitattributes delete mode 100644 internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH create mode 100644 vendored/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH rename {internal => vendored}/durabletask-protobuf/README.md (64%) rename {internal => vendored}/durabletask-protobuf/protos/orchestrator_service.proto (100%) rename {internal => vendored}/durabletask-protobuf/update-proto.sh (51%) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfdb8b7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index a57873e..42da255 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -73,7 +73,7 @@ jobs: go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@$PROTOC_GEN_GO_GRPC - name: Generate grpc code - run: protoc --go_out=. --go-grpc_out=. -I ./internal/durabletask-protobuf/protos orchestrator_service.proto + run: protoc --go_out=. --go-grpc_out=. -I ./vendored/durabletask-protobuf/protos orchestrator_service.proto - name: Run go vet run: go vet ./... diff --git a/CHANGELOG.md b/CHANGELOG.md index bc252b9..267ccf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Removed the `submodules/durabletask-protobuf` git submodule. The `orchestrator_service.proto` file is now vendored under `internal/durabletask-protobuf/protos/`, with the source commit hash tracked in `internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH` and a helper script (`internal/durabletask-protobuf/update-proto.sh`) for refreshing the proto from upstream. +- Removed the `submodules/durabletask-protobuf` git submodule. The `orchestrator_service.proto` file is now vendored under `vendored/durabletask-protobuf/protos/`, with the source provenance (URL, branch/ref, commit hash) tracked in `vendored/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH` and a helper script (`vendored/durabletask-protobuf/update-proto.sh`) for refreshing the proto from upstream. ## [v0.6.0] - 2025-02-05 diff --git a/README.md b/README.md index 74aea2b..1377d17 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ Clone the repository as you normally would: git clone https://github.com/microsoft/durabletask-go ``` -The protocol buffer definitions used to generate the gRPC bindings are vendored under [`internal/durabletask-protobuf/protos`](./internal/durabletask-protobuf/protos). See [`internal/durabletask-protobuf/README.md`](./internal/durabletask-protobuf/README.md) for details on how to refresh them from the upstream [microsoft/durabletask-protobuf](https://github.com/microsoft/durabletask-protobuf) repository. +The protocol buffer definitions used to generate the gRPC bindings are vendored under [`vendored/durabletask-protobuf/protos`](./vendored/durabletask-protobuf/protos). See [`vendored/durabletask-protobuf/README.md`](./vendored/durabletask-protobuf/README.md) for details on how to refresh them from the upstream [microsoft/durabletask-protobuf](https://github.com/microsoft/durabletask-protobuf) repository. ## Building the project @@ -261,11 +261,11 @@ This project requires go v1.19.x or greater. You can build a standalone executab ### Generating protobuf -Use the following command to regenerate the protobuf bindings from the vendored proto file. Use this whenever updating the proto file under [`internal/durabletask-protobuf/protos`](./internal/durabletask-protobuf/protos). +Use the following command to regenerate the protobuf bindings from the vendored proto file. Use this whenever updating the proto file under [`vendored/durabletask-protobuf/protos`](./vendored/durabletask-protobuf/protos). ```bash # NOTE: assumes the .proto file defines: option go_package = "/internal/protos" -protoc --go_out=. --go-grpc_out=. -I internal/durabletask-protobuf/protos orchestrator_service.proto +protoc --go_out=. --go-grpc_out=. -I vendored/durabletask-protobuf/protos orchestrator_service.proto ``` ### Generating mocks for testing diff --git a/internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH b/internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH deleted file mode 100644 index d9d80bf..0000000 --- a/internal/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH +++ /dev/null @@ -1 +0,0 @@ -4207e1dbd14cedc268f69c3befee60fcaad19367 \ No newline at end of file diff --git a/vendored/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH b/vendored/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH new file mode 100644 index 0000000..049687a --- /dev/null +++ b/vendored/durabletask-protobuf/PROTO_SOURCE_COMMIT_HASH @@ -0,0 +1,4 @@ +Source: https://github.com/microsoft/durabletask-protobuf +Branch: main +Commit: 4207e1dbd14cedc268f69c3befee60fcaad19367 +URL: https://github.com/microsoft/durabletask-protobuf/blob/4207e1dbd14cedc268f69c3befee60fcaad19367/protos/orchestrator_service.proto \ No newline at end of file diff --git a/internal/durabletask-protobuf/README.md b/vendored/durabletask-protobuf/README.md similarity index 64% rename from internal/durabletask-protobuf/README.md rename to vendored/durabletask-protobuf/README.md index 28590e7..36341fe 100644 --- a/internal/durabletask-protobuf/README.md +++ b/vendored/durabletask-protobuf/README.md @@ -5,7 +5,7 @@ This directory contains the protocol buffer definitions used by the Durable Task ## Directory Structure - `protos/` - Contains the vendored proto files -- `PROTO_SOURCE_COMMIT_HASH` - Contains the commit hash of the upstream `microsoft/durabletask-protobuf` repository that the proto files were last synced from +- `PROTO_SOURCE_COMMIT_HASH` - Records the upstream source URL, branch/ref, and commit hash that the proto files were last synced from - `update-proto.sh` - Helper script to refresh the vendored proto file and commit hash from upstream ## Updating the proto files @@ -14,16 +14,16 @@ Run the helper script from the repository root to download the latest `orchestra ```bash # Update from the default branch (main) -./internal/durabletask-protobuf/update-proto.sh +./vendored/durabletask-protobuf/update-proto.sh -# Update from a specific branch -./internal/durabletask-protobuf/update-proto.sh +# Update from a specific branch, tag, or commit SHA +./vendored/durabletask-protobuf/update-proto.sh ``` After running the script, regenerate the Go gRPC bindings so that the committed `internal/protos/*.pb.go` files match the updated `.proto`: ```bash -protoc --go_out=. --go-grpc_out=. -I ./internal/durabletask-protobuf/protos orchestrator_service.proto +protoc --go_out=. --go-grpc_out=. -I ./vendored/durabletask-protobuf/protos orchestrator_service.proto ``` -Commit both the updated proto file, `PROTO_SOURCE_COMMIT_HASH`, and the regenerated `.pb.go` files together. +Commit the updated proto file, `PROTO_SOURCE_COMMIT_HASH`, and the regenerated `.pb.go` files together. diff --git a/internal/durabletask-protobuf/protos/orchestrator_service.proto b/vendored/durabletask-protobuf/protos/orchestrator_service.proto similarity index 100% rename from internal/durabletask-protobuf/protos/orchestrator_service.proto rename to vendored/durabletask-protobuf/protos/orchestrator_service.proto diff --git a/internal/durabletask-protobuf/update-proto.sh b/vendored/durabletask-protobuf/update-proto.sh similarity index 51% rename from internal/durabletask-protobuf/update-proto.sh rename to vendored/durabletask-protobuf/update-proto.sh index 72f89e2..b5b22ab 100755 --- a/internal/durabletask-protobuf/update-proto.sh +++ b/vendored/durabletask-protobuf/update-proto.sh @@ -1,17 +1,20 @@ #!/usr/bin/env bash # Downloads the latest orchestrator_service.proto from the -# microsoft/durabletask-protobuf repository and writes the source -# commit hash to PROTO_SOURCE_COMMIT_HASH. +# microsoft/durabletask-protobuf repository and writes provenance +# information (source URL, branch/ref, commit hash, file URL) to +# PROTO_SOURCE_COMMIT_HASH. # # Usage: -# ./internal/durabletask-protobuf/update-proto.sh [branch] +# ./vendored/durabletask-protobuf/update-proto.sh [ref] # -# If [branch] is omitted, "main" is used. +# `ref` may be a branch name, tag name, or commit SHA. +# If omitted, "main" is used. set -euo pipefail -BRANCH="${1:-main}" +REF="${1:-main}" REPO="microsoft/durabletask-protobuf" +REPO_URL="https://github.com/${REPO}" PROTO_PATH="protos/orchestrator_service.proto" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" @@ -25,21 +28,25 @@ if [[ -n "${GITHUB_TOKEN:-}" ]]; then CURL_AUTH=(-H "Authorization: Bearer ${GITHUB_TOKEN}") fi -echo "Resolving latest commit for ${PROTO_PATH} on ${REPO}@${BRANCH}..." -COMMIT_API_URL="https://api.github.com/repos/${REPO}/commits?path=${PROTO_PATH}&sha=${BRANCH}&per_page=1" +echo "Resolving latest commit for ${PROTO_PATH} on ${REPO}@${REF}..." +COMMIT_API_URL="https://api.github.com/repos/${REPO}/commits?path=${PROTO_PATH}&sha=${REF}&per_page=1" COMMIT_RESPONSE=$(curl -fsSL \ "${CURL_AUTH[@]}" \ -H "Accept: application/vnd.github.v3+json" \ "${COMMIT_API_URL}") # Extract the first "sha": "" value from the JSON response. +# Use sed -nE so a missing match leaves COMMIT_HASH empty and the +# validation block below can emit a clear error, instead of the +# pipeline aborting silently under `set -euo pipefail`. COMMIT_HASH=$(printf '%s' "${COMMIT_RESPONSE}" \ - | grep -o '"sha"[[:space:]]*:[[:space:]]*"[^"]*"' \ - | head -n 1 \ - | sed -E 's/.*"sha"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/') + | sed -nE 's/.*"sha"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' \ + | head -n 1) if [[ -z "${COMMIT_HASH}" ]]; then echo "Failed to resolve commit hash from ${COMMIT_API_URL}" >&2 + echo "Response was:" >&2 + printf '%s\n' "${COMMIT_RESPONSE}" >&2 exit 1 fi @@ -48,10 +55,15 @@ curl -fsSL \ "https://raw.githubusercontent.com/${REPO}/${COMMIT_HASH}/${PROTO_PATH}" \ -o "${PROTO_DIR}/orchestrator_service.proto" -echo "${COMMIT_HASH}" > "${HASH_FILE}" +cat > "${HASH_FILE}" <