mirror of https://github.com/dapr/go-sdk.git
				
				
				
			Implement distributed scheduler building block (#562)
* feat: add jobs/scheduling api (with validation override) Signed-off-by: mikeee <hey@mike.ee> * chore: fix deps Signed-off-by: mikeee <hey@mike.ee> * fix: use cli fix Signed-off-by: mikeee <hey@mike.ee> * fix: ci artifact path set for cli build Signed-off-by: mikeee <hey@mike.ee> * chore: remove sidecar step Signed-off-by: mikeee <hey@mike.ee> * chore: revert changes to other examples Signed-off-by: mikeee <hey@mike.ee> --------- Signed-off-by: mikeee <hey@mike.ee> Signed-off-by: Mike Nguyen <hey@mike.ee>
This commit is contained in:
		
							parent
							
								
									01c0f3154f
								
							
						
					
					
						commit
						967570515b
					
				| 
						 | 
					@ -23,6 +23,8 @@ jobs:
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Checkout
 | 
					      - name: Checkout
 | 
				
			||||||
        uses: actions/checkout@v4
 | 
					        uses: actions/checkout@v4
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          submodules: recursive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Setup
 | 
					      - name: Setup
 | 
				
			||||||
        uses: actions/setup-go@v5
 | 
					        uses: actions/setup-go@v5
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,10 +39,12 @@ jobs:
 | 
				
			||||||
    outputs:
 | 
					    outputs:
 | 
				
			||||||
      DAPR_INSTALL_URL: ${{ env.DAPR_INSTALL_URL }}
 | 
					      DAPR_INSTALL_URL: ${{ env.DAPR_INSTALL_URL }}
 | 
				
			||||||
      DAPR_CLI_VER: ${{ steps.outputs.outputs.DAPR_CLI_VER }}
 | 
					      DAPR_CLI_VER: ${{ steps.outputs.outputs.DAPR_CLI_VER }}
 | 
				
			||||||
      DAPR_RUNTIME_VER: ${{ steps.outputs.outputs.DAPR_RUNTIME_VER }}
 | 
					      DAPR_CLI_REF: ${{ steps.outputs.outputs.DAPR_CLI_REF }}
 | 
				
			||||||
 | 
					      DAPR_RUNTIME_VER: 1.14.0-rc.2
 | 
				
			||||||
      CHECKOUT_REPO: ${{ steps.outputs.outputs.CHECKOUT_REPO }}
 | 
					      CHECKOUT_REPO: ${{ steps.outputs.outputs.CHECKOUT_REPO }}
 | 
				
			||||||
      CHECKOUT_REF: ${{ steps.outputs.outputs.CHECKOUT_REF }}
 | 
					      CHECKOUT_REF: ${{ steps.outputs.outputs.CHECKOUT_REF }}
 | 
				
			||||||
      DAPR_REF: ${{ steps.outputs.outputs.DAPR_REF }}
 | 
					      DAPR_REF: ${{ steps.outputs.outputs.DAPR_REF }}
 | 
				
			||||||
 | 
					      GITHUB_SHA: ${{ steps.outputs.outputs.GITHUB_SHA }}
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - name: Parse repository_dispatch payload
 | 
					      - name: Parse repository_dispatch payload
 | 
				
			||||||
        if: github.event_name == 'repository_dispatch'
 | 
					        if: github.event_name == 'repository_dispatch'
 | 
				
			||||||
| 
						 | 
					@ -79,9 +81,6 @@ jobs:
 | 
				
			||||||
          echo "DAPR_CLI_VER=$CLI_VERSION" >> $GITHUB_ENV
 | 
					          echo "DAPR_CLI_VER=$CLI_VERSION" >> $GITHUB_ENV
 | 
				
			||||||
          echo "Found $CLI_VERSION"
 | 
					          echo "Found $CLI_VERSION"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Set up Dapr CLI
 | 
					 | 
				
			||||||
        run: wget -q ${{ env.DAPR_INSTALL_URL }} -O - | /bin/bash -s ${{ env.DAPR_CLI_VER }}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      - name: Checkout Dapr CLI repo to override dapr command.
 | 
					      - name: Checkout Dapr CLI repo to override dapr command.
 | 
				
			||||||
        uses: actions/checkout@v4
 | 
					        uses: actions/checkout@v4
 | 
				
			||||||
        if: env.DAPR_CLI_REF != ''
 | 
					        if: env.DAPR_CLI_REF != ''
 | 
				
			||||||
| 
						 | 
					@ -105,17 +104,19 @@ jobs:
 | 
				
			||||||
          cd cli
 | 
					          cd cli
 | 
				
			||||||
          make
 | 
					          make
 | 
				
			||||||
          mkdir -p $HOME/artifacts/$GITHUB_SHA/
 | 
					          mkdir -p $HOME/artifacts/$GITHUB_SHA/
 | 
				
			||||||
          sudo cp dist/linux_amd64/release/dapr $HOME/artifacts/$GITHUB_SHA/dapr
 | 
					          sudo cp dist/linux_amd64/release/dapr ~/artifacts/$GITHUB_SHA/dapr
 | 
				
			||||||
 | 
					          echo "artifactPath=~/artifacts/$GITHUB_SHA/" >> $GITHUB_ENV
 | 
				
			||||||
 | 
					          echo "DAPR_CLI_REF=$DAPR_CLI_REF" >> $GITHUB_ENV
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Build daprd and placement with referenced commit.
 | 
					      - name: Build dapr
 | 
				
			||||||
        if: env.DAPR_REF != ''
 | 
					        if: env.DAPR_REF != ''
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          echo "artifactPath=~/artifacts/$GITHUB_SHA/" >> $GITHUB_ENV
 | 
					          echo "artifactPath=~/artifacts/$GITHUB_SHA/" >> $GITHUB_ENV
 | 
				
			||||||
          cd dapr_runtime
 | 
					          cd dapr_runtime
 | 
				
			||||||
          make
 | 
					          make
 | 
				
			||||||
          mkdir -p $HOME/artifacts/$GITHUB_SHA/
 | 
					          mkdir -p $HOME/artifacts/$GITHUB_SHA/
 | 
				
			||||||
          cp dist/linux_amd64/release/daprd $HOME/artifacts/$GITHUB_SHA/daprd
 | 
					          echo "artifactPath=~/artifacts/$GITHUB_SHA/" >> $GITHUB_ENV
 | 
				
			||||||
          cp dist/linux_amd64/release/placement $HOME/artifacts/$GITHUB_SHA/placement
 | 
					          cp ./dist/linux_amd64/release/* ~/artifacts/$GITHUB_SHA/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Upload dapr-artifacts
 | 
					      - name: Upload dapr-artifacts
 | 
				
			||||||
        uses: actions/upload-artifact@v4
 | 
					        uses: actions/upload-artifact@v4
 | 
				
			||||||
| 
						 | 
					@ -132,10 +133,12 @@ jobs:
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          echo "DAPR_INSTALL_URL=$DAPR_INSTALL_URL"
 | 
					          echo "DAPR_INSTALL_URL=$DAPR_INSTALL_URL"
 | 
				
			||||||
          echo "DAPR_CLI_VER=$DAPR_CLI_VER" >> "$GITHUB_OUTPUT"
 | 
					          echo "DAPR_CLI_VER=$DAPR_CLI_VER" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
 | 
					          echo "DAPR_CLI_REF=$DAPR_CLI_REF" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
          echo "DAPR_RUNTIME_VER=$DAPR_RUNTIME_VER" >> "$GITHUB_OUTPUT"
 | 
					          echo "DAPR_RUNTIME_VER=$DAPR_RUNTIME_VER" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
          echo "CHECKOUT_REPO=$CHECKOUT_REPO" >> "$GITHUB_OUTPUT"
 | 
					          echo "CHECKOUT_REPO=$CHECKOUT_REPO" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
          echo "CHECKOUT_REF=$CHECKOUT_REF" >> "$GITHUB_OUTPUT"
 | 
					          echo "CHECKOUT_REF=$CHECKOUT_REF" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
          echo "DAPR_REF=$DAPR_REF" >> "$GITHUB_OUTPUT"
 | 
					          echo "DAPR_REF=$DAPR_REF" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
 | 
					          echo "GITHUB_SHA=$GITHUB_SHA" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  validate-example:
 | 
					  validate-example:
 | 
				
			||||||
    needs: setup
 | 
					    needs: setup
 | 
				
			||||||
| 
						 | 
					@ -148,10 +151,11 @@ jobs:
 | 
				
			||||||
      DAPR_INSTALL_URL: ${{ needs.setup.outputs.DAPR_INSTALL_URL }}
 | 
					      DAPR_INSTALL_URL: ${{ needs.setup.outputs.DAPR_INSTALL_URL }}
 | 
				
			||||||
      DAPR_CLI_VER: ${{ needs.setup.outputs.DAPR_CLI_VER }}
 | 
					      DAPR_CLI_VER: ${{ needs.setup.outputs.DAPR_CLI_VER }}
 | 
				
			||||||
      DAPR_RUNTIME_VER: 1.14.0-rc.2
 | 
					      DAPR_RUNTIME_VER: 1.14.0-rc.2
 | 
				
			||||||
      DAPR_CLI_REF: ${{ github.event.inputs.daprcli_commit }}
 | 
					      DAPR_CLI_REF: ${{ needs.setup.outputs.DAPR_CLI_REF }}
 | 
				
			||||||
      DAPR_REF: ${{ github.event.inputs.daprdapr_commit }}
 | 
					      DAPR_REF: ${{ needs.setup.outputs.DAPR_REF }}
 | 
				
			||||||
      CHECKOUT_REPO: ${{ needs.setup.outputs.CHECKOUT_REPO }}
 | 
					      CHECKOUT_REPO: ${{ needs.setup.outputs.CHECKOUT_REPO }}
 | 
				
			||||||
      CHECKOUT_REF: ${{ needs.setup.outputs.CHECKOUT_REF }}
 | 
					      CHECKOUT_REF: ${{ needs.setup.outputs.CHECKOUT_REF }}
 | 
				
			||||||
 | 
					      GITHUB_SHA: ${{ needs.setup.outputs.GITHUB_SHA }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
      fail-fast: false
 | 
					      fail-fast: false
 | 
				
			||||||
| 
						 | 
					@ -161,6 +165,7 @@ jobs:
 | 
				
			||||||
            "actor",
 | 
					            "actor",
 | 
				
			||||||
            "configuration",
 | 
					            "configuration",
 | 
				
			||||||
            "crypto",
 | 
					            "crypto",
 | 
				
			||||||
 | 
					            "dist-scheduler",
 | 
				
			||||||
            "grpc-service",
 | 
					            "grpc-service",
 | 
				
			||||||
            "hello-world",
 | 
					            "hello-world",
 | 
				
			||||||
            "pubsub",
 | 
					            "pubsub",
 | 
				
			||||||
| 
						 | 
					@ -187,7 +192,11 @@ jobs:
 | 
				
			||||||
        uses: actions/download-artifact@v4
 | 
					        uses: actions/download-artifact@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          name: dapr-artifacts
 | 
					          name: dapr-artifacts
 | 
				
			||||||
          path: $HOME/artifacts/$GITHUB_SHA/
 | 
					          path: ~/artifacts/${{ env.GITHUB_SHA }}/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Display artifacts downloaded
 | 
				
			||||||
 | 
					        if: env.DAPR_CLI_REF != '' || env.DAPR_REF != ''
 | 
				
			||||||
 | 
					        run: ls ~/artifacts/$GITHUB_SHA/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Set up Go
 | 
					      - name: Set up Go
 | 
				
			||||||
        id: setup-go
 | 
					        id: setup-go
 | 
				
			||||||
| 
						 | 
					@ -196,6 +205,7 @@ jobs:
 | 
				
			||||||
          go-version-file: "go.mod"
 | 
					          go-version-file: "go.mod"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Set up Dapr CLI
 | 
					      - name: Set up Dapr CLI
 | 
				
			||||||
 | 
					        if: env.DAPR_CLI_VER != ''
 | 
				
			||||||
        run: wget -q ${{ env.DAPR_INSTALL_URL }} -O - | /bin/bash -s ${{ env.DAPR_CLI_VER }}
 | 
					        run: wget -q ${{ env.DAPR_INSTALL_URL }} -O - | /bin/bash -s ${{ env.DAPR_CLI_VER }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Override dapr cli with referenced commit.
 | 
					      - name: Override dapr cli with referenced commit.
 | 
				
			||||||
| 
						 | 
					@ -208,13 +218,15 @@ jobs:
 | 
				
			||||||
          dapr uninstall --all
 | 
					          dapr uninstall --all
 | 
				
			||||||
          dapr init --runtime-version ${{ env.DAPR_RUNTIME_VER }}
 | 
					          dapr init --runtime-version ${{ env.DAPR_RUNTIME_VER }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Override daprd and placement service with referenced commit.
 | 
					      - name: Print scheduler logs
 | 
				
			||||||
 | 
					        run: |
 | 
				
			||||||
 | 
					          docker logs dapr_scheduler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Override daprd with referenced commit.
 | 
				
			||||||
        if: env.DAPR_REF != ''
 | 
					        if: env.DAPR_REF != ''
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          mkdir -p $HOME/.dapr/bin/
 | 
					          mkdir -p $HOME/.dapr/bin/
 | 
				
			||||||
          cp $HOME/artifacts/$GITHUB_SHA/daprd $HOME/.dapr/bin/daprd
 | 
					          cp $HOME/artifacts/$GITHUB_SHA/daprd $HOME/.dapr/bin/daprd
 | 
				
			||||||
          docker stop dapr_placement
 | 
					 | 
				
			||||||
          $HOME/artifacts/$GITHUB_SHA/placement --healthz-port 9091 &
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Set up Python ${{ env.PYTHON_VER }}
 | 
					      - name: Set up Python ${{ env.PYTHON_VER }}
 | 
				
			||||||
        uses: actions/setup-python@v5
 | 
					        uses: actions/setup-python@v5
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,6 +250,15 @@ type Client interface {
 | 
				
			||||||
	// RaiseEventWorkflowBeta1 raises an event for a workflow.
 | 
						// RaiseEventWorkflowBeta1 raises an event for a workflow.
 | 
				
			||||||
	RaiseEventWorkflowBeta1(ctx context.Context, req *RaiseEventWorkflowRequest) error
 | 
						RaiseEventWorkflowBeta1(ctx context.Context, req *RaiseEventWorkflowRequest) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ScheduleJobAlpha1 creates and schedules a job.
 | 
				
			||||||
 | 
						ScheduleJobAlpha1(ctx context.Context, req *Job) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// GetJobAlpha1 returns a scheduled job.
 | 
				
			||||||
 | 
						GetJobAlpha1(ctx context.Context, name string) (*Job, error)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DeleteJobAlpha1 deletes a scheduled job.
 | 
				
			||||||
 | 
						DeleteJobAlpha1(ctx context.Context, name string) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// GrpcClient returns the base grpc client if grpc is used and nil otherwise
 | 
						// GrpcClient returns the base grpc client if grpc is used and nil otherwise
 | 
				
			||||||
	GrpcClient() pb.DaprClient
 | 
						GrpcClient() pb.DaprClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -557,6 +557,33 @@ func (s *testDaprServer) RaiseEventWorkflowBeta1(ctx context.Context, in *pb.Rai
 | 
				
			||||||
	return &emptypb.Empty{}, nil
 | 
						return &emptypb.Empty{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *testDaprServer) ScheduleJobAlpha1(ctx context.Context, in *pb.ScheduleJobRequest) (*pb.ScheduleJobResponse, error) {
 | 
				
			||||||
 | 
						return &pb.ScheduleJobResponse{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *testDaprServer) GetJobAlpha1(ctx context.Context, in *pb.GetJobRequest) (*pb.GetJobResponse, error) {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							schedule        = "@every 10s"
 | 
				
			||||||
 | 
							dueTime         = "10s"
 | 
				
			||||||
 | 
							repeats  uint32 = 4
 | 
				
			||||||
 | 
							ttl             = "10s"
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						return &pb.GetJobResponse{
 | 
				
			||||||
 | 
							Job: &pb.Job{
 | 
				
			||||||
 | 
								Name:     "name",
 | 
				
			||||||
 | 
								Schedule: &schedule,
 | 
				
			||||||
 | 
								Repeats:  &repeats,
 | 
				
			||||||
 | 
								DueTime:  &dueTime,
 | 
				
			||||||
 | 
								Ttl:      &ttl,
 | 
				
			||||||
 | 
								Data:     nil,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *testDaprServer) DeleteJobAlpha1(ctx context.Context, in *pb.DeleteJobRequest) (*pb.DeleteJobResponse, error) {
 | 
				
			||||||
 | 
						return &pb.DeleteJobResponse{}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestGrpcClient(t *testing.T) {
 | 
					func TestGrpcClient(t *testing.T) {
 | 
				
			||||||
	protoClient := pb.NewDaprClient(nil)
 | 
						protoClient := pb.NewDaprClient(nil)
 | 
				
			||||||
	client := &GRPCClient{protoClient: protoClient}
 | 
						client := &GRPCClient{protoClient: protoClient}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,91 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2021 The Dapr Authors
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/anypb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pb "github.com/dapr/dapr/pkg/proto/runtime/v1"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Job struct {
 | 
				
			||||||
 | 
						Name     string
 | 
				
			||||||
 | 
						Schedule string
 | 
				
			||||||
 | 
						Repeats  uint32 // Optional
 | 
				
			||||||
 | 
						DueTime  string // Optional
 | 
				
			||||||
 | 
						TTL      string // Optional
 | 
				
			||||||
 | 
						Data     *anypb.Any
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ScheduleJobAlpha1 raises and schedules a job.
 | 
				
			||||||
 | 
					func (c *GRPCClient) ScheduleJobAlpha1(ctx context.Context, job *Job) error {
 | 
				
			||||||
 | 
						// TODO: Assert job fields are defined: Name, Schedule, Data
 | 
				
			||||||
 | 
						jobRequest := &pb.Job{
 | 
				
			||||||
 | 
							Name:     job.Name,
 | 
				
			||||||
 | 
							Schedule: &job.Schedule,
 | 
				
			||||||
 | 
							Data:     job.Data,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if job.Schedule != "" {
 | 
				
			||||||
 | 
							jobRequest.Schedule = &job.Schedule
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if job.Repeats != 0 {
 | 
				
			||||||
 | 
							jobRequest.Repeats = &job.Repeats
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if job.DueTime != "" {
 | 
				
			||||||
 | 
							jobRequest.DueTime = &job.DueTime
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if job.TTL != "" {
 | 
				
			||||||
 | 
							jobRequest.Ttl = &job.TTL
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err := c.protoClient.ScheduleJobAlpha1(ctx, &pb.ScheduleJobRequest{
 | 
				
			||||||
 | 
							Job: jobRequest,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetJobAlpha1 retrieves a scheduled job.
 | 
				
			||||||
 | 
					func (c *GRPCClient) GetJobAlpha1(ctx context.Context, name string) (*Job, error) {
 | 
				
			||||||
 | 
						// TODO: Name validation
 | 
				
			||||||
 | 
						resp, err := c.protoClient.GetJobAlpha1(ctx, &pb.GetJobRequest{
 | 
				
			||||||
 | 
							Name: name,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						log.Println(resp)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &Job{
 | 
				
			||||||
 | 
							Name:     resp.GetJob().GetName(),
 | 
				
			||||||
 | 
							Schedule: resp.GetJob().GetSchedule(),
 | 
				
			||||||
 | 
							Repeats:  resp.GetJob().GetRepeats(),
 | 
				
			||||||
 | 
							DueTime:  resp.GetJob().GetDueTime(),
 | 
				
			||||||
 | 
							TTL:      resp.GetJob().GetTtl(),
 | 
				
			||||||
 | 
							Data:     resp.GetJob().GetData(),
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DeleteJobAlpha1 deletes a scheduled job.
 | 
				
			||||||
 | 
					func (c *GRPCClient) DeleteJobAlpha1(ctx context.Context, name string) error {
 | 
				
			||||||
 | 
						// TODO: Name validation
 | 
				
			||||||
 | 
						_, err := c.protoClient.DeleteJobAlpha1(ctx, &pb.DeleteJobRequest{
 | 
				
			||||||
 | 
							Name: name,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,58 @@
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2021 The Dapr Authors
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/anypb"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSchedulingAlpha1(t *testing.T) {
 | 
				
			||||||
 | 
						ctx := context.Background()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Run("schedule job - valid", func(t *testing.T) {
 | 
				
			||||||
 | 
							err := testClient.ScheduleJobAlpha1(ctx, &Job{
 | 
				
			||||||
 | 
								Name:     "test",
 | 
				
			||||||
 | 
								Schedule: "test",
 | 
				
			||||||
 | 
								Data:     &anypb.Any{},
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							require.NoError(t, err)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Run("get job - valid", func(t *testing.T) {
 | 
				
			||||||
 | 
							expected := &Job{
 | 
				
			||||||
 | 
								Name:     "name",
 | 
				
			||||||
 | 
								Schedule: "@every 10s",
 | 
				
			||||||
 | 
								Repeats:  4,
 | 
				
			||||||
 | 
								DueTime:  "10s",
 | 
				
			||||||
 | 
								TTL:      "10s",
 | 
				
			||||||
 | 
								Data:     nil,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							resp, err := testClient.GetJobAlpha1(ctx, "name")
 | 
				
			||||||
 | 
							require.NoError(t, err)
 | 
				
			||||||
 | 
							assert.Equal(t, expected, resp)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Run("delete job - valid", func(t *testing.T) {
 | 
				
			||||||
 | 
							err := testClient.DeleteJobAlpha1(ctx, "name")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							require.NoError(t, err)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					# Dapr Distributed Scheduler Example with go-sdk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Steps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Prepare
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Dapr installed (v1.14 or higher)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Run Distributed Scheduling Example
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- STEP
 | 
				
			||||||
 | 
					name: Run Distributed Scheduling Example
 | 
				
			||||||
 | 
					output_match_mode: substring
 | 
				
			||||||
 | 
					expected_stdout_lines:
 | 
				
			||||||
 | 
					  - 'Scheduler stream connected'
 | 
				
			||||||
 | 
					  - 'schedulejob - success'
 | 
				
			||||||
 | 
					  - 'job 0 received'
 | 
				
			||||||
 | 
					  - 'extracted payload: {db-backup {my-prod-db /backup-dir}}'
 | 
				
			||||||
 | 
					  - 'job 1 received'
 | 
				
			||||||
 | 
					  - 'extracted payload: {db-backup {my-prod-db /backup-dir}}'
 | 
				
			||||||
 | 
					  - 'job 2 received'
 | 
				
			||||||
 | 
					  - 'extracted payload: {db-backup {my-prod-db /backup-dir}}'
 | 
				
			||||||
 | 
					  - 'getjob - resp: &{prod-db-backup @every 1s 10   value:"{\"task\":\"db-backup\",\"metadata\":{\"db_name\":\"my-prod-db\",\"backup_location\":\"/backup-dir\"}}"}'
 | 
				
			||||||
 | 
					  - 'deletejob - success'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					background: true
 | 
				
			||||||
 | 
					sleep: 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					         dapr run --app-id=distributed-scheduler \
 | 
				
			||||||
 | 
					                --metrics-port=9091 \
 | 
				
			||||||
 | 
					                --scheduler-host-address=localhost:50006 \
 | 
				
			||||||
 | 
					                --dapr-grpc-port 50001 \
 | 
				
			||||||
 | 
					                --app-port 50070 \
 | 
				
			||||||
 | 
					                --app-protocol grpc \
 | 
				
			||||||
 | 
					                --log-level debug \
 | 
				
			||||||
 | 
					                go run ./main.go
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<!-- END_STEP -->
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,11 @@
 | 
				
			||||||
 | 
					package api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Metadata struct {
 | 
				
			||||||
 | 
						DBName         string `json:"db_name"`
 | 
				
			||||||
 | 
						BackupLocation string `json:"backup_location"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type DBBackup struct {
 | 
				
			||||||
 | 
						Task     string   `json:"task"`
 | 
				
			||||||
 | 
						Metadata Metadata `json:"metadata"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,114 @@
 | 
				
			||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/base64"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/anypb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						daprc "github.com/dapr/go-sdk/client"
 | 
				
			||||||
 | 
						"github.com/dapr/go-sdk/examples/dist-scheduler/api"
 | 
				
			||||||
 | 
						"github.com/dapr/go-sdk/service/common"
 | 
				
			||||||
 | 
						daprs "github.com/dapr/go-sdk/service/grpc"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						server, err := daprs.NewService(":50070")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("failed to start the server: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = server.AddJobEventHandler("prod-db-backup", prodDBBackupHandler); err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("failed to register job event handler: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Println("starting server")
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							if err = server.Start(); err != nil {
 | 
				
			||||||
 | 
								log.Fatalf("failed to start server: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Brief intermission to allow for the server to initialize.
 | 
				
			||||||
 | 
						time.Sleep(10 * time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx := context.Background()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						jobData, err := json.Marshal(&api.DBBackup{
 | 
				
			||||||
 | 
							Task: "db-backup",
 | 
				
			||||||
 | 
							Metadata: api.Metadata{
 | 
				
			||||||
 | 
								DBName:         "my-prod-db",
 | 
				
			||||||
 | 
								BackupLocation: "/backup-dir",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						job := daprc.Job{
 | 
				
			||||||
 | 
							Name:     "prod-db-backup",
 | 
				
			||||||
 | 
							Schedule: "@every 1s",
 | 
				
			||||||
 | 
							Repeats:  10,
 | 
				
			||||||
 | 
							Data: &anypb.Any{
 | 
				
			||||||
 | 
								Value: jobData,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// create the client
 | 
				
			||||||
 | 
						client, err := daprc.NewClient()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer client.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = client.ScheduleJobAlpha1(ctx, &job)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println("schedulejob - success")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						time.Sleep(3 * time.Second)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := client.GetJobAlpha1(ctx, "prod-db-backup")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							panic(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Printf("getjob - resp: %v\n", resp) // parse
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = client.DeleteJobAlpha1(ctx, "prod-db-backup")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Printf("job deletion error: %v\n", err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fmt.Println("deletejob - success")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err = server.Stop(); err != nil {
 | 
				
			||||||
 | 
							log.Fatalf("failed to stop server: %v\n", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var jobCount = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func prodDBBackupHandler(ctx context.Context, job *common.JobEvent) error {
 | 
				
			||||||
 | 
						var jobData common.Job
 | 
				
			||||||
 | 
						if err := json.Unmarshal(job.Data, &jobData); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to unmarshal job: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						decodedPayload, err := base64.StdEncoding.DecodeString(jobData.Value)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to decode job payload: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var jobPayload api.DBBackup
 | 
				
			||||||
 | 
						if err := json.Unmarshal(decodedPayload, &jobPayload); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to unmarshal payload: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Printf("job %d received:\n type: %v \n typeurl: %v\n value: %v\n extracted payload: %v\n", jobCount, job.JobType, jobData.TypeURL, jobData.Value, jobPayload)
 | 
				
			||||||
 | 
						jobCount++
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
module github.com/dapr/go-sdk/examples
 | 
					module github.com/dapr/go-sdk/examples
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.22.4
 | 
					go 1.22.5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
replace github.com/dapr/go-sdk => ../
 | 
					replace github.com/dapr/go-sdk => ../
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,14 +10,15 @@ require (
 | 
				
			||||||
	github.com/go-redis/redis/v8 v8.11.5
 | 
						github.com/go-redis/redis/v8 v8.11.5
 | 
				
			||||||
	github.com/google/uuid v1.6.0
 | 
						github.com/google/uuid v1.6.0
 | 
				
			||||||
	google.golang.org/grpc v1.65.0
 | 
						google.golang.org/grpc v1.65.0
 | 
				
			||||||
	google.golang.org/grpc/examples v0.0.0-20240529235625-24e902437554
 | 
						google.golang.org/grpc/examples v0.0.0-20240516203910-e22436abb809
 | 
				
			||||||
 | 
						google.golang.org/protobuf v1.34.2
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
 | 
						github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
 | 
				
			||||||
	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
 | 
						github.com/cenkalti/backoff/v4 v4.3.0 // indirect
 | 
				
			||||||
	github.com/cespare/xxhash/v2 v2.3.0 // indirect
 | 
						github.com/cespare/xxhash/v2 v2.3.0 // indirect
 | 
				
			||||||
	github.com/dapr/dapr v1.14.0-rc.1 // indirect
 | 
						github.com/dapr/dapr v1.14.0-rc.2 // indirect
 | 
				
			||||||
	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 | 
						github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 | 
				
			||||||
	github.com/go-chi/chi/v5 v5.1.0 // indirect
 | 
						github.com/go-chi/chi/v5 v5.1.0 // indirect
 | 
				
			||||||
	github.com/go-logr/logr v1.4.2 // indirect
 | 
						github.com/go-logr/logr v1.4.2 // indirect
 | 
				
			||||||
| 
						 | 
					@ -34,6 +35,5 @@ require (
 | 
				
			||||||
	golang.org/x/sys v0.21.0 // indirect
 | 
						golang.org/x/sys v0.21.0 // indirect
 | 
				
			||||||
	golang.org/x/text v0.16.0 // indirect
 | 
						golang.org/x/text v0.16.0 // indirect
 | 
				
			||||||
	google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect
 | 
						google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d // indirect
 | 
				
			||||||
	google.golang.org/protobuf v1.34.2 // indirect
 | 
					 | 
				
			||||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
						gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,8 @@ github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyY
 | 
				
			||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
 | 
					github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
 | 
				
			||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
					github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
				
			||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
					github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
				
			||||||
github.com/dapr/dapr v1.14.0-rc.1 h1:4P376+PIU66hMtLz5TiF41IJ6Lh5FNY1DiwaNNYZv/8=
 | 
					github.com/dapr/dapr v1.14.0-rc.2 h1:wuXninZLTyokeztCinVIVAc9mpVYJS8QyxecPCLdlY8=
 | 
				
			||||||
github.com/dapr/dapr v1.14.0-rc.1/go.mod h1:uZMuD9K7y+LKSsQUoSAvv1Yn8Cim9X/9ZQ9XuTobyP8=
 | 
					github.com/dapr/dapr v1.14.0-rc.2/go.mod h1:uZMuD9K7y+LKSsQUoSAvv1Yn8Cim9X/9ZQ9XuTobyP8=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 | 
					github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
| 
						 | 
					@ -77,8 +77,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:
 | 
				
			||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
 | 
					google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
 | 
				
			||||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
 | 
					google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
 | 
				
			||||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
 | 
					google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
 | 
				
			||||||
google.golang.org/grpc/examples v0.0.0-20240529235625-24e902437554 h1:w4+xIPcgnCPx2fCAcl+9XZ4wA7tpurRvJ+KBSgAig4A=
 | 
					google.golang.org/grpc/examples v0.0.0-20240516203910-e22436abb809 h1:f96Rv5C5Y2CWlbKK6KhKDdyFgGOjPHPEMsdyaxE9k0c=
 | 
				
			||||||
google.golang.org/grpc/examples v0.0.0-20240529235625-24e902437554/go.mod h1:zVJi9R2NecTook3ihvrayAmkYWKtOfRrvL+2eRtKdMk=
 | 
					google.golang.org/grpc/examples v0.0.0-20240516203910-e22436abb809/go.mod h1:uaPEAc5V00jjG3DPhGFLXGT290RUV3+aNQigs1W50/8=
 | 
				
			||||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
 | 
					google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
 | 
				
			||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
 | 
					google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										6
									
								
								go.mod
								
								
								
								
							| 
						 | 
					@ -1,11 +1,9 @@
 | 
				
			||||||
module github.com/dapr/go-sdk
 | 
					module github.com/dapr/go-sdk
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.22.4
 | 
					go 1.22.5
 | 
				
			||||||
 | 
					 | 
				
			||||||
toolchain go1.22.5
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/dapr/dapr v1.14.0-rc.1
 | 
						github.com/dapr/dapr v1.14.0-rc.2
 | 
				
			||||||
	github.com/go-chi/chi/v5 v5.1.0
 | 
						github.com/go-chi/chi/v5 v5.1.0
 | 
				
			||||||
	github.com/golang/mock v1.6.0
 | 
						github.com/golang/mock v1.6.0
 | 
				
			||||||
	github.com/google/uuid v1.6.0
 | 
						github.com/google/uuid v1.6.0
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										4
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										4
									
								
								go.sum
								
								
								
								
							| 
						 | 
					@ -1,8 +1,8 @@
 | 
				
			||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
 | 
					github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
 | 
				
			||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
 | 
					github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
 | 
				
			||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
					github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
 | 
				
			||||||
github.com/dapr/dapr v1.14.0-rc.1 h1:4P376+PIU66hMtLz5TiF41IJ6Lh5FNY1DiwaNNYZv/8=
 | 
					github.com/dapr/dapr v1.14.0-rc.2 h1:wuXninZLTyokeztCinVIVAc9mpVYJS8QyxecPCLdlY8=
 | 
				
			||||||
github.com/dapr/dapr v1.14.0-rc.1/go.mod h1:uZMuD9K7y+LKSsQUoSAvv1Yn8Cim9X/9ZQ9XuTobyP8=
 | 
					github.com/dapr/dapr v1.14.0-rc.2/go.mod h1:uZMuD9K7y+LKSsQUoSAvv1Yn8Cim9X/9ZQ9XuTobyP8=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 | 
					github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
 | 
					github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,6 +42,9 @@ type Service interface {
 | 
				
			||||||
	RegisterActorImplFactory(f actor.Factory, opts ...config.Option)
 | 
						RegisterActorImplFactory(f actor.Factory, opts ...config.Option)
 | 
				
			||||||
	// RegisterActorImplFactoryContext Register a new actor to actor runtime of go sdk
 | 
						// RegisterActorImplFactoryContext Register a new actor to actor runtime of go sdk
 | 
				
			||||||
	RegisterActorImplFactoryContext(f actor.FactoryContext, opts ...config.Option)
 | 
						RegisterActorImplFactoryContext(f actor.FactoryContext, opts ...config.Option)
 | 
				
			||||||
 | 
						// AddJobEventHandler appends a provided job event handler with its name to
 | 
				
			||||||
 | 
						// the service.
 | 
				
			||||||
 | 
						AddJobEventHandler(name string, fn JobEventHandler) error
 | 
				
			||||||
	// Start starts service.
 | 
						// Start starts service.
 | 
				
			||||||
	Start() error
 | 
						Start() error
 | 
				
			||||||
	// Stop stops the previously started service.
 | 
						// Stop stops the previously started service.
 | 
				
			||||||
| 
						 | 
					@ -54,5 +57,6 @@ type (
 | 
				
			||||||
	ServiceInvocationHandler func(ctx context.Context, in *InvocationEvent) (out *Content, err error)
 | 
						ServiceInvocationHandler func(ctx context.Context, in *InvocationEvent) (out *Content, err error)
 | 
				
			||||||
	TopicEventHandler        func(ctx context.Context, e *TopicEvent) (retry bool, err error)
 | 
						TopicEventHandler        func(ctx context.Context, e *TopicEvent) (retry bool, err error)
 | 
				
			||||||
	BindingInvocationHandler func(ctx context.Context, in *BindingEvent) (out []byte, err error)
 | 
						BindingInvocationHandler func(ctx context.Context, in *BindingEvent) (out []byte, err error)
 | 
				
			||||||
 | 
						JobEventHandler          func(ctx context.Context, in *JobEvent) error
 | 
				
			||||||
	HealthCheckHandler       func(context.Context) error
 | 
						HealthCheckHandler       func(context.Context) error
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,3 +120,13 @@ const (
 | 
				
			||||||
type SubscriptionResponse struct {
 | 
					type SubscriptionResponse struct {
 | 
				
			||||||
	Status SubscriptionResponseStatus `json:"status"`
 | 
						Status SubscriptionResponseStatus `json:"status"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type JobEvent struct {
 | 
				
			||||||
 | 
						JobType string `json:"job_type"`
 | 
				
			||||||
 | 
						Data    []byte `json:"data"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Job struct {
 | 
				
			||||||
 | 
						TypeURL string `json:"type_url"`
 | 
				
			||||||
 | 
						Value   string `json:"value"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,50 @@
 | 
				
			||||||
 | 
					package grpc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						runtimepb "github.com/dapr/dapr/pkg/proto/runtime/v1"
 | 
				
			||||||
 | 
						"github.com/dapr/go-sdk/service/common"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// AddJobEventHandler registers a job handler
 | 
				
			||||||
 | 
					func (s *Server) AddJobEventHandler(name string, fn common.JobEventHandler) error {
 | 
				
			||||||
 | 
						if name == "" {
 | 
				
			||||||
 | 
							return errors.New("job event name cannot be empty")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if fn == nil {
 | 
				
			||||||
 | 
							return errors.New("job event handler not supplied")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s.jobEventHandlers[name] = fn
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// OnJobEvent is invoked by the sidecar following a scheduled job registered in
 | 
				
			||||||
 | 
					// the scheduler
 | 
				
			||||||
 | 
					func (s *Server) OnJobEventAlpha1(ctx context.Context, in *runtimepb.JobEventRequest) (*runtimepb.JobEventResponse, error) {
 | 
				
			||||||
 | 
						// parse the job type from the method or name
 | 
				
			||||||
 | 
						jobType, found := strings.CutPrefix(in.GetMethod(), "job/")
 | 
				
			||||||
 | 
						if !found {
 | 
				
			||||||
 | 
							if in.GetName() == "" {
 | 
				
			||||||
 | 
								return &runtimepb.JobEventResponse{}, errors.New("unsupported invocation")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							jobType = in.GetName()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if fn, ok := s.jobEventHandlers[jobType]; ok {
 | 
				
			||||||
 | 
							e := &common.JobEvent{
 | 
				
			||||||
 | 
								JobType: jobType,
 | 
				
			||||||
 | 
								Data:    in.GetData().GetValue(),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := fn(ctx, e); err != nil {
 | 
				
			||||||
 | 
								return nil, fmt.Errorf("error executing %s binding: %w", in.GetName(), err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return &runtimepb.JobEventResponse{}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &runtimepb.JobEventResponse{}, errors.New("job event handler not found")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -55,11 +55,12 @@ func NewServiceWithGrpcServer(lis net.Listener, server *grpc.Server) common.Serv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newService(lis net.Listener, grpcServer *grpc.Server, opts ...grpc.ServerOption) *Server {
 | 
					func newService(lis net.Listener, grpcServer *grpc.Server, opts ...grpc.ServerOption) *Server {
 | 
				
			||||||
	s := &Server{
 | 
						s := &Server{
 | 
				
			||||||
		listener:        lis,
 | 
							listener:         lis,
 | 
				
			||||||
		invokeHandlers:  make(map[string]common.ServiceInvocationHandler),
 | 
							invokeHandlers:   make(map[string]common.ServiceInvocationHandler),
 | 
				
			||||||
		topicRegistrar:  make(internal.TopicRegistrar),
 | 
							topicRegistrar:   make(internal.TopicRegistrar),
 | 
				
			||||||
		bindingHandlers: make(map[string]common.BindingInvocationHandler),
 | 
							bindingHandlers:  make(map[string]common.BindingInvocationHandler),
 | 
				
			||||||
		authToken:       os.Getenv(common.AppAPITokenEnvVar),
 | 
							jobEventHandlers: make(map[string]common.JobEventHandler),
 | 
				
			||||||
 | 
							authToken:        os.Getenv(common.AppAPITokenEnvVar),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if grpcServer == nil {
 | 
						if grpcServer == nil {
 | 
				
			||||||
| 
						 | 
					@ -67,6 +68,7 @@ func newService(lis net.Listener, grpcServer *grpc.Server, opts ...grpc.ServerOp
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pb.RegisterAppCallbackServer(grpcServer, s)
 | 
						pb.RegisterAppCallbackServer(grpcServer, s)
 | 
				
			||||||
 | 
						pb.RegisterAppCallbackAlphaServer(grpcServer, s)
 | 
				
			||||||
	pb.RegisterAppCallbackHealthCheckServer(grpcServer, s)
 | 
						pb.RegisterAppCallbackHealthCheckServer(grpcServer, s)
 | 
				
			||||||
	s.grpcServer = grpcServer
 | 
						s.grpcServer = grpcServer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,6 +83,7 @@ type Server struct {
 | 
				
			||||||
	invokeHandlers     map[string]common.ServiceInvocationHandler
 | 
						invokeHandlers     map[string]common.ServiceInvocationHandler
 | 
				
			||||||
	topicRegistrar     internal.TopicRegistrar
 | 
						topicRegistrar     internal.TopicRegistrar
 | 
				
			||||||
	bindingHandlers    map[string]common.BindingInvocationHandler
 | 
						bindingHandlers    map[string]common.BindingInvocationHandler
 | 
				
			||||||
 | 
						jobEventHandlers   map[string]common.JobEventHandler
 | 
				
			||||||
	healthCheckHandler common.HealthCheckHandler
 | 
						healthCheckHandler common.HealthCheckHandler
 | 
				
			||||||
	authToken          string
 | 
						authToken          string
 | 
				
			||||||
	grpcServer         *grpc.Server
 | 
						grpcServer         *grpc.Server
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -169,3 +169,7 @@ func getCustomMetadataFromContext(ctx context.Context) map[string]string {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return md
 | 
						return md
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Server) OnBulkTopicEventAlpha1(ctx context.Context, in *runtimev1pb.TopicEventBulkRequest) (*runtimev1pb.TopicEventBulkResponse, error) {
 | 
				
			||||||
 | 
						panic("This API callback is not supported.")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					package http
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/dapr/go-sdk/service/common"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Server) AddJobEventHandler(name string, fn common.JobEventHandler) error {
 | 
				
			||||||
 | 
						if name == "" {
 | 
				
			||||||
 | 
							return fmt.Errorf("job event name required")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if fn == nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("job event handler required")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return errors.New("handling http scheduling requests has not been implemented in this sdk")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue