Skip to content

Commit ed1c770

Browse files
feat: Create RPCs are idempotent
1 parent 01d77fe commit ed1c770

File tree

9 files changed

+98
-45
lines changed

9 files changed

+98
-45
lines changed

cmd/saga/start/service/service.go

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
package service
33

44
import (
5-
"context"
6-
"fmt"
7-
85
temporalConnect "buf.build/gen/go/kevinmichaelchen/temporalapis/connectrpc/go/temporal/v1beta1/temporalv1beta1connect"
96
temporalPB "buf.build/gen/go/kevinmichaelchen/temporalapis/protocolbuffers/go/temporal/v1beta1"
107
"connectrpc.com/connect"
8+
"context"
9+
"fmt"
1110
"github.com/bufbuild/protovalidate-go"
11+
"github.com/google/uuid"
1212
"github.com/sirupsen/logrus"
1313
"go.temporal.io/sdk/client"
1414

@@ -53,10 +53,24 @@ func (s *Service) CreateOnboardingWorkflow(
5353
TaskQueue: saga.CreateLicenseTaskQueue,
5454
}
5555

56+
orgID := uuid.New().String()
57+
profileID := uuid.New().String()
58+
5659
args := saga.CreateLicenseInputArgs{
57-
OrgName: req.Msg.GetOrg().GetName(),
58-
ProfileName: req.Msg.GetProfile().GetName(),
59-
LicenseName: "New License",
60+
Org: saga.Org{
61+
ID: orgID,
62+
Name: req.Msg.GetOrg().GetName(),
63+
},
64+
Profile: saga.Profile{
65+
ID: profileID,
66+
FullName: req.Msg.GetProfile().GetFullName(),
67+
},
68+
License: saga.License{
69+
ID: uuid.New().String(),
70+
Start: req.Msg.GetLicense().GetStart().AsTime(),
71+
End: req.Msg.GetLicense().GetEnd().AsTime(),
72+
UserID: profileID,
73+
},
6074
}
6175

6276
workflow, err := temporalClient.ExecuteWorkflow(
@@ -83,9 +97,8 @@ func (s *Service) CreateOnboardingWorkflow(
8397

8498
func printResults(args saga.CreateLicenseInputArgs, workflowID, runID string) {
8599
logrus.WithFields(logrus.Fields{
86-
"org_name": args.OrgName,
87-
"profile_name": args.ProfileName,
88-
"license_name": args.LicenseName,
100+
"org_name": args.Org.Name,
101+
"profile_name": args.Profile.FullName,
89102
"temporal.workflow_id": workflowID,
90103
"temporal.run_id": runID,
91104
}).Info("Successfully completed Workflow")

cmd/saga/start/service/validate_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestValidate(t *testing.T) {
2929
Name: "Name",
3030
},
3131
Profile: &temporalPB.Profile{
32-
Name: "Name",
32+
FullName: "Name",
3333
},
3434
}
3535
}

cmd/svc/license/service/service.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ func (s *Service) CreateLicense(
7373

7474
res := &licensev1beta1.CreateLicenseResponse{}
7575

76-
logrus.WithField("name", req.Msg.GetName()).Info("Creating License")
76+
logrus.
77+
WithField("id", req.Msg.GetId()).
78+
WithField("user_id", req.Msg.GetUserId()).
79+
WithField("start", req.Msg.GetStart()).
80+
WithField("end", req.Msg.GetEnd()).
81+
Info("Creating License")
7782

7883
out := connect.NewResponse(res)
7984
out.Header().Set("API-Version", "v1beta1")

cmd/svc/org/service/service.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ func (s *Service) CreateOrg(
4343

4444
res := &orgPB.CreateOrgResponse{}
4545

46-
logrus.WithField("name", req.Msg.GetName()).Info("Creating Org")
46+
logrus.
47+
WithField("id", req.Msg.GetId()).
48+
WithField("name", req.Msg.GetName()).
49+
Info("Creating Org")
4750

4851
out := connect.NewResponse(res)
4952
out.Header().Set("API-Version", "v1beta1")

cmd/svc/profile/service/service.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ func (s *Service) CreateProfile(
4343

4444
res := &profilePB.CreateProfileResponse{}
4545

46-
logrus.WithField("name", req.Msg.GetName()).Info("Creating Profile")
46+
logrus.
47+
WithField("id", req.Msg.GetId()).
48+
WithField("org_id", req.Msg.GetOrgId()).
49+
WithField("name", req.Msg.GetFullName()).
50+
Info("Creating Profile")
4751

4852
out := connect.NewResponse(res)
4953
out.Header().Set("API-Version", "v1beta1")

go.mod

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ module github.com/kevinmichaelchen/temporal-saga-grpc
33
go 1.21.5
44

55
require (
6-
buf.build/gen/go/kevinmichaelchen/licenseapis/connectrpc/go v1.14.0-20231230182852-a5b0c8441680.1
7-
buf.build/gen/go/kevinmichaelchen/licenseapis/protocolbuffers/go v1.32.0-20231230182852-a5b0c8441680.1
8-
buf.build/gen/go/kevinmichaelchen/orgapis/connectrpc/go v1.14.0-20231230143300-f1e12ab42c62.1
9-
buf.build/gen/go/kevinmichaelchen/orgapis/protocolbuffers/go v1.32.0-20231230143300-f1e12ab42c62.1
10-
buf.build/gen/go/kevinmichaelchen/profileapis/connectrpc/go v1.14.0-20231230143301-839882cce539.1
11-
buf.build/gen/go/kevinmichaelchen/profileapis/protocolbuffers/go v1.32.0-20231230143301-839882cce539.1
12-
buf.build/gen/go/kevinmichaelchen/temporalapis/connectrpc/go v1.14.0-20231230182854-8d9d2e3ad33c.1
13-
buf.build/gen/go/kevinmichaelchen/temporalapis/protocolbuffers/go v1.32.0-20231230182854-8d9d2e3ad33c.1
6+
buf.build/gen/go/kevinmichaelchen/licenseapis/connectrpc/go v1.14.0-20240105230935-96a83ee74301.1
7+
buf.build/gen/go/kevinmichaelchen/licenseapis/protocolbuffers/go v1.32.0-20240105230935-96a83ee74301.1
8+
buf.build/gen/go/kevinmichaelchen/orgapis/connectrpc/go v1.14.0-20240105230936-cc69561a5883.1
9+
buf.build/gen/go/kevinmichaelchen/orgapis/protocolbuffers/go v1.32.0-20240105230936-cc69561a5883.1
10+
buf.build/gen/go/kevinmichaelchen/profileapis/connectrpc/go v1.14.0-20240105230937-9f5a2b967cc7.1
11+
buf.build/gen/go/kevinmichaelchen/profileapis/protocolbuffers/go v1.32.0-20240105230937-9f5a2b967cc7.1
12+
buf.build/gen/go/kevinmichaelchen/temporalapis/connectrpc/go v1.14.0-20240105224636-721997cf176e.1
13+
buf.build/gen/go/kevinmichaelchen/temporalapis/protocolbuffers/go v1.32.0-20240105224636-721997cf176e.1
1414
connectrpc.com/connect v1.14.0
1515
connectrpc.com/grpchealth v1.3.0
1616
connectrpc.com/grpcreflect v1.2.0
@@ -25,7 +25,7 @@ require (
2525
github.com/stretchr/testify v1.8.4
2626
github.com/volatiletech/null/v8 v8.1.2
2727
github.com/volatiletech/sqlboiler/v4 v4.15.0
28-
github.com/volatiletech/strmangle v0.0.5
28+
github.com/volatiletech/strmangle v0.0.6
2929
go.opentelemetry.io/otel v1.21.0
3030
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0
3131
go.opentelemetry.io/otel/sdk v1.21.0

go.sum

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.32.0-20231115204500-e097f827e652.1 h1:u0olL4yf2p7Tl5jfsAK5keaFi+JFJuv1CDHrbiXkxkk=
22
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.32.0-20231115204500-e097f827e652.1/go.mod h1:tiTMKD8j6Pd/D2WzREoweufjzaJKHZg35f/VGcZ2v3I=
3-
buf.build/gen/go/kevinmichaelchen/licenseapis/connectrpc/go v1.14.0-20231230182852-a5b0c8441680.1 h1:Li+ostVf9g8qR1aXY5JyQJJCsszfazjWSigIfG5F+gQ=
4-
buf.build/gen/go/kevinmichaelchen/licenseapis/connectrpc/go v1.14.0-20231230182852-a5b0c8441680.1/go.mod h1:AnmQTTp9GU6KlMj64LOa2aj0ZLeY+7g8n3RfH+tNO4c=
5-
buf.build/gen/go/kevinmichaelchen/licenseapis/protocolbuffers/go v1.32.0-20231230182852-a5b0c8441680.1 h1:iP5aO8HJdXvq7pL+EKLq3I6wkw37KS9BTtizhO/m8V4=
6-
buf.build/gen/go/kevinmichaelchen/licenseapis/protocolbuffers/go v1.32.0-20231230182852-a5b0c8441680.1/go.mod h1:f0zTv4+cZ3+O0fQx7E6JKpPLhQuUJMkl+M7Ott4b4wo=
7-
buf.build/gen/go/kevinmichaelchen/orgapis/connectrpc/go v1.14.0-20231230143300-f1e12ab42c62.1 h1:GvCPyGpxUQ1GK6dZ63fuAqnULnRGaVzTuN3xdMGpUj0=
8-
buf.build/gen/go/kevinmichaelchen/orgapis/connectrpc/go v1.14.0-20231230143300-f1e12ab42c62.1/go.mod h1:k9MXsI946kP98De3USAMI1C+FJa23s2cbJQRgDa7ebY=
9-
buf.build/gen/go/kevinmichaelchen/orgapis/protocolbuffers/go v1.32.0-20231230143300-f1e12ab42c62.1 h1:VLe/5LqsGoc+P2b0dW/u1/ppt6TUap0dzwU27k4hFUw=
10-
buf.build/gen/go/kevinmichaelchen/orgapis/protocolbuffers/go v1.32.0-20231230143300-f1e12ab42c62.1/go.mod h1:01Q17lfPPU5yLwTfmXR7xxcgheeltV8MnYDOBK/76UE=
11-
buf.build/gen/go/kevinmichaelchen/profileapis/connectrpc/go v1.14.0-20231230143301-839882cce539.1 h1:h0uNblC7l/WCFK2SoxWbaR/YHoNN4JPOQopgFMPezLQ=
12-
buf.build/gen/go/kevinmichaelchen/profileapis/connectrpc/go v1.14.0-20231230143301-839882cce539.1/go.mod h1:feIZBXMSAhget6j1/h9kospvcT9gd71lMRYVv9S/N0A=
13-
buf.build/gen/go/kevinmichaelchen/profileapis/protocolbuffers/go v1.32.0-20231230143301-839882cce539.1 h1:Cf1gSTF6fcrqwwZonbKV3vtiGW9NmBxq2czibB80ReA=
14-
buf.build/gen/go/kevinmichaelchen/profileapis/protocolbuffers/go v1.32.0-20231230143301-839882cce539.1/go.mod h1:CThAb0pmoNp60CIAHgS3gRBKiFL50Frrsw1pfWGzodg=
15-
buf.build/gen/go/kevinmichaelchen/temporalapis/connectrpc/go v1.14.0-20231230182854-8d9d2e3ad33c.1 h1:In+vy2TA5flkwluSZDfUepAMuhNFu/p43PxvcTVzD8E=
16-
buf.build/gen/go/kevinmichaelchen/temporalapis/connectrpc/go v1.14.0-20231230182854-8d9d2e3ad33c.1/go.mod h1:4pucHCVy5j99kBB5OYo5a0IZQCcmzxUAF4/4/oYIgSg=
17-
buf.build/gen/go/kevinmichaelchen/temporalapis/protocolbuffers/go v1.32.0-20231230182854-8d9d2e3ad33c.1 h1:M/lKXqOTBbQhYf9PpswPYpAvDHtImHtUMSg5xZiHSvo=
18-
buf.build/gen/go/kevinmichaelchen/temporalapis/protocolbuffers/go v1.32.0-20231230182854-8d9d2e3ad33c.1/go.mod h1:2Mpji+rUNpkV7r9a5cIDXpKJMRYmp0I0XrM61EBLEDY=
3+
buf.build/gen/go/kevinmichaelchen/licenseapis/connectrpc/go v1.14.0-20240105230935-96a83ee74301.1 h1:iz8B4/o/Tu9kCU1O61ce9LoMO4cruyKOxZg+Xn3jkIk=
4+
buf.build/gen/go/kevinmichaelchen/licenseapis/connectrpc/go v1.14.0-20240105230935-96a83ee74301.1/go.mod h1:TWnyka2/a0+psN92AVScMT7Sq3mKdjCAWLjcfLQDMgk=
5+
buf.build/gen/go/kevinmichaelchen/licenseapis/protocolbuffers/go v1.32.0-20240105230935-96a83ee74301.1 h1:uxRlX4/HFwA//ZcSZdryz5Nk9hzsLWRUMnmJjwQGA7s=
6+
buf.build/gen/go/kevinmichaelchen/licenseapis/protocolbuffers/go v1.32.0-20240105230935-96a83ee74301.1/go.mod h1:f0zTv4+cZ3+O0fQx7E6JKpPLhQuUJMkl+M7Ott4b4wo=
7+
buf.build/gen/go/kevinmichaelchen/orgapis/connectrpc/go v1.14.0-20240105230936-cc69561a5883.1 h1:w6j+cfXANJ3mFei+DLs8afQp305z35sSXJdrVTP+Kig=
8+
buf.build/gen/go/kevinmichaelchen/orgapis/connectrpc/go v1.14.0-20240105230936-cc69561a5883.1/go.mod h1:2c3rsXGY3Zpto2kEM0hr3bTrvRqcUQzlPF5Glj/Xjno=
9+
buf.build/gen/go/kevinmichaelchen/orgapis/protocolbuffers/go v1.32.0-20240105230936-cc69561a5883.1 h1:pHMAxU1GI79GvmdTi2mfOKDRaPWqZ7UqMSoyxBVLp9U=
10+
buf.build/gen/go/kevinmichaelchen/orgapis/protocolbuffers/go v1.32.0-20240105230936-cc69561a5883.1/go.mod h1:VX7SaxTl48U3BUn1ZWGPaw3Z3trZei6Lijff1hWDCmM=
11+
buf.build/gen/go/kevinmichaelchen/profileapis/connectrpc/go v1.14.0-20240105230937-9f5a2b967cc7.1 h1:+pGDboLYUQSzr+YieYCoY1AP9RtL69rLKhBx5tNzwT4=
12+
buf.build/gen/go/kevinmichaelchen/profileapis/connectrpc/go v1.14.0-20240105230937-9f5a2b967cc7.1/go.mod h1:yZWWCij9/6ffN2PJwEYWgs7DjkWa5cXl2AR8Xvnc+Ng=
13+
buf.build/gen/go/kevinmichaelchen/profileapis/protocolbuffers/go v1.32.0-20240105230937-9f5a2b967cc7.1 h1:YaUHKKR7AZRrnCiZ+QOQuw2wQB0DlOe8KBdN7bDymhs=
14+
buf.build/gen/go/kevinmichaelchen/profileapis/protocolbuffers/go v1.32.0-20240105230937-9f5a2b967cc7.1/go.mod h1:mdFxPRDe6P7qFVw9urFLZ3SkG+ZdPW5q5QXFGjGr8DE=
15+
buf.build/gen/go/kevinmichaelchen/temporalapis/connectrpc/go v1.14.0-20240105224636-721997cf176e.1 h1:JRUSsAPd9V5UQFPYs1dckEwRS0R/bAQtCRlRRQ+n9Pw=
16+
buf.build/gen/go/kevinmichaelchen/temporalapis/connectrpc/go v1.14.0-20240105224636-721997cf176e.1/go.mod h1:2PeRAbDFPMunT2xjMRMjvkzCGgilVlNWYwgYRatp3/4=
17+
buf.build/gen/go/kevinmichaelchen/temporalapis/protocolbuffers/go v1.32.0-20240105224636-721997cf176e.1 h1:3dN5NHBYnXnHPa2qG22eeVYNG/ZwAni9potlZz6XcNA=
18+
buf.build/gen/go/kevinmichaelchen/temporalapis/protocolbuffers/go v1.32.0-20240105224636-721997cf176e.1/go.mod h1:2Mpji+rUNpkV7r9a5cIDXpKJMRYmp0I0XrM61EBLEDY=
1919
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2020
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2121
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -1317,8 +1317,9 @@ github.com/volatiletech/randomize v0.0.1/go.mod h1:GN3U0QYqfZ9FOJ67bzax1cqZ5q2xu
13171317
github.com/volatiletech/sqlboiler/v4 v4.15.0 h1:+twm3mA34SaUF6wB9U6QkXxkK8AKkV5EfgMSvcKWeY4=
13181318
github.com/volatiletech/sqlboiler/v4 v4.15.0/go.mod h1:s643wqYyCQ7Ak2hMVxH7kTS0+lFPNlj+gHKUIukJ0YA=
13191319
github.com/volatiletech/strmangle v0.0.1/go.mod h1:F6RA6IkB5vq0yTG4GQ0UsbbRcl3ni9P76i+JrTBKFFg=
1320-
github.com/volatiletech/strmangle v0.0.5 h1:CompJPy+lAi9h+YU/IzBR4X2RDRuAuEIP+kjFdyZXcU=
13211320
github.com/volatiletech/strmangle v0.0.5/go.mod h1:ycDvbDkjDvhC0NUU8w3fWwl5JEMTV56vTKXzR3GeR+0=
1321+
github.com/volatiletech/strmangle v0.0.6 h1:AdOYE3B2ygRDq4rXDij/MMwq6KVK/pWAYxpC7CLrkKQ=
1322+
github.com/volatiletech/strmangle v0.0.6/go.mod h1:ycDvbDkjDvhC0NUU8w3fWwl5JEMTV56vTKXzR3GeR+0=
13221323
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
13231324
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
13241325
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=

pkg/saga/activity.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package saga
33
import (
44
"context"
55
"fmt"
6+
"google.golang.org/protobuf/types/known/timestamppb"
67

78
license "buf.build/gen/go/kevinmichaelchen/licenseapis/protocolbuffers/go/license/v1beta1"
89
org "buf.build/gen/go/kevinmichaelchen/orgapis/protocolbuffers/go/org/v1beta1"
@@ -14,7 +15,8 @@ import (
1415
func (c *Controller) CreateOrg(ctx context.Context, args CreateLicenseInputArgs) error {
1516
_, err := c.orgClient.CreateOrg(ctx, connect.NewRequest(
1617
&org.CreateOrgRequest{
17-
Name: args.OrgName,
18+
Id: args.Org.ID,
19+
Name: args.Org.Name,
1820
},
1921
))
2022
if err != nil {
@@ -28,7 +30,9 @@ func (c *Controller) CreateOrg(ctx context.Context, args CreateLicenseInputArgs)
2830
func (c *Controller) CreateProfile(ctx context.Context, args CreateLicenseInputArgs) error {
2931
_, err := c.profileClient.CreateProfile(ctx, connect.NewRequest(
3032
&profile.CreateProfileRequest{
31-
Name: args.ProfileName,
33+
Id: args.Profile.ID,
34+
OrgId: args.Profile.OrgID,
35+
FullName: args.Profile.FullName,
3236
},
3337
))
3438
if err != nil {
@@ -42,7 +46,10 @@ func (c *Controller) CreateProfile(ctx context.Context, args CreateLicenseInputA
4246
func (c *Controller) CreateLicense(ctx context.Context, args CreateLicenseInputArgs) error {
4347
_, err := c.licenseClient.CreateLicense(ctx, connect.NewRequest(
4448
&license.CreateLicenseRequest{
45-
Name: args.LicenseName,
49+
Id: args.License.ID,
50+
Start: timestamppb.New(args.License.Start),
51+
End: timestamppb.New(args.License.End),
52+
UserId: args.License.UserID,
4653
},
4754
))
4855
if err != nil {

pkg/saga/shared.go

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,31 @@
11
package saga
22

3+
import "time"
4+
35
// CreateLicenseTaskQueue - Queue name for workflow tasks.
46
const CreateLicenseTaskQueue = "CREATE_LICENSE_TASK_QUEUE"
57

68
// CreateLicenseInputArgs - Arguments to kick off the Temporal workflow.
79
type CreateLicenseInputArgs struct {
8-
OrgName string
9-
ProfileName string
10-
LicenseName string
10+
Org Org
11+
Profile Profile
12+
License License
13+
}
14+
15+
type Org struct {
16+
ID string
17+
Name string
18+
}
19+
20+
type Profile struct {
21+
ID string
22+
FullName string
23+
OrgID string
24+
}
25+
26+
type License struct {
27+
ID string
28+
Start time.Time
29+
End time.Time
30+
UserID string
1131
}

0 commit comments

Comments
 (0)