diff --git a/components/fctl/cmd/orchestration/triggers/occurrences/list.go b/components/fctl/cmd/orchestration/triggers/occurrences/list.go index 6027a494b8..b404241ae2 100644 --- a/components/fctl/cmd/orchestration/triggers/occurrences/list.go +++ b/components/fctl/cmd/orchestration/triggers/occurrences/list.go @@ -91,15 +91,23 @@ func (c *OccurrencesListController) Render(cmd *cobra.Command, args []string) er fctl.Map(c.store.WorkflowOccurrence, func(src shared.TriggerOccurrence) []string { return []string{ - src.WorkflowInstanceID, + func() string { + if src.WorkflowInstanceID != nil { + return "" + } + return *src.WorkflowInstanceID + }(), src.Date.Format(time.RFC3339), fctl.BoolToString(src.WorkflowInstance.Terminated), src.WorkflowInstance.TerminatedAt.Format(time.RFC3339), func() string { - if src.WorkflowInstance.Error == nil { - return "" + if src.Error != nil && *src.Error != "" { + return *src.Error + } + if src.WorkflowInstance != nil && src.WorkflowInstance.Error != nil && *src.WorkflowInstance.Error != "" { + return *src.WorkflowInstance.Error } - return *src.WorkflowInstance.Error + return "" }(), } }), diff --git a/components/ledger/internal/posting.go b/components/ledger/internal/posting.go index 7bb9011bf5..fb6c5d7b4d 100644 --- a/components/ledger/internal/posting.go +++ b/components/ledger/internal/posting.go @@ -59,6 +59,9 @@ func (p *Postings) Scan(value interface{}) error { func (p Postings) Validate() (int, error) { for i, p := range p { + if p.Amount == nil { + return i, errors.New("no amount defined") + } if p.Amount.Cmp(Zero) < 0 { return i, errors.New("negative amount") } diff --git a/components/ledger/libs/publish/cli.go b/components/ledger/libs/publish/cli.go index 0032d8a1c7..591339fc87 100644 --- a/components/ledger/libs/publish/cli.go +++ b/components/ledger/libs/publish/cli.go @@ -96,16 +96,14 @@ func InitCLIFlags(cmd *cobra.Command, options ...func(*ConfigDefault)) { cmd.PersistentFlags().Int(PublisherKafkaSASLScramSHASizeFlag, values.PublisherKafkaSASLScramSHASize, "SASL SCRAM SHA size") cmd.PersistentFlags().Bool(PublisherKafkaTLSEnabledFlag, values.PublisherKafkaTLSEnabled, "Enable TLS to connect on kafka") - // NATS - InitNatsCliFlags(cmd, options...) + InitNatsCLIFlags(cmd, options...) } -func InitNatsCliFlags(cmd *cobra.Command, options ...func(*ConfigDefault)) { +func InitNatsCLIFlags(cmd *cobra.Command, options ...func(*ConfigDefault)) { values := defaultConfigValues for _, option := range options { option(&values) } - // NATS cmd.PersistentFlags().Bool(PublisherNatsEnabledFlag, values.PublisherNatsEnabled, "Publish write events to nats") cmd.PersistentFlags().String(PublisherNatsClientIDFlag, values.PublisherNatsClientID, "Nats client ID") diff --git a/components/ledger/libs/publish/nats.go b/components/ledger/libs/publish/nats.go index f8857c797a..07f3d5ca8c 100644 --- a/components/ledger/libs/publish/nats.go +++ b/components/ledger/libs/publish/nats.go @@ -44,7 +44,7 @@ func NatsModule(url, serviceName string, natsOptions ...nats.Option) fx.Option { fx.Provide(NewNatsPublisherWithConn), fx.Provide(NewNatsSubscriberWithConn), fx.Provide(func(natsCallbacks NATSCallbacks) wNats.PublisherConfig { - natsOptions = AppendCallBacks(natsOptions, natsCallbacks) + natsOptions = AppendNatsCallBacks(natsOptions, natsCallbacks) return wNats.PublisherConfig{ NatsOptions: natsOptions, URL: url, @@ -54,7 +54,7 @@ func NatsModule(url, serviceName string, natsOptions ...nats.Option) fx.Option { } }), fx.Provide(func(natsCallbacks NATSCallbacks) wNats.SubscriberConfig { - natsOptions = AppendCallBacks(natsOptions, natsCallbacks) + natsOptions = AppendNatsCallBacks(natsOptions, natsCallbacks) return wNats.SubscriberConfig{ NatsOptions: natsOptions, Unmarshaler: &wNats.NATSMarshaler{}, @@ -88,7 +88,7 @@ type NATSCallbacks interface { AsyncErrorCB(nc *nats.Conn, sub *nats.Subscription, err error) } -func AppendCallBacks(natsOptions []nats.Option, c NATSCallbacks) []nats.Option { +func AppendNatsCallBacks(natsOptions []nats.Option, c NATSCallbacks) []nats.Option { return append(natsOptions, nats.ConnectHandler(c.ConnectedCB), nats.DisconnectErrHandler(c.DisconnectedErrCB), diff --git a/ee/orchestration/internal/storage/migrations.go b/ee/orchestration/internal/storage/migrations.go index 466fefaacc..a49b12f47f 100644 --- a/ee/orchestration/internal/storage/migrations.go +++ b/ee/orchestration/internal/storage/migrations.go @@ -116,6 +116,17 @@ add primary key (instance_id, stage, temporal_run_id); return nil }, }, + { + Up: func(tx bun.Tx) error { + if _, err := tx.Exec(` +alter table "triggers_occurrences" +add column error varchar; + `); err != nil { + return err + } + return nil + }, + }, } func Migrate(ctx context.Context, db *bun.DB) error { diff --git a/ee/orchestration/internal/triggers/activity.go b/ee/orchestration/internal/triggers/activity.go index ee868e6ced..c1108119e4 100644 --- a/ee/orchestration/internal/triggers/activity.go +++ b/ee/orchestration/internal/triggers/activity.go @@ -5,6 +5,10 @@ import ( "encoding/json" "strings" + sharedlogging "github.com/formancehq/stack/libs/go-libs/logging" + + "go.temporal.io/sdk/temporal" + "github.com/formancehq/orchestration/internal/workflow" "github.com/formancehq/stack/libs/go-libs/collectionutils" "github.com/formancehq/stack/libs/go-libs/pointer" @@ -74,35 +78,42 @@ func (a Activities) ProcessTrigger(ctx context.Context, trigger Trigger, request span := trace.SpanFromContext(ctx) var ( - evaluated map[string]string - err error + evaluated map[string]string + triggerError error + occurrence = NewTriggerOccurrence(request.MessageID, trigger.ID, request.Event) ) if trigger.Vars != nil { - evaluated, err = a.expressionEvaluator.evalVariables(request.Event.Payload, trigger.Vars) - if err != nil { - span.RecordError(err) - return err - } + evaluated, triggerError = a.expressionEvaluator.evalVariables(request.Event.Payload, trigger.Vars) } + if triggerError == nil { + data, triggerError := json.Marshal(evaluated) + if triggerError != nil { + panic(triggerError) + } - data, err := json.Marshal(evaluated) - if err != nil { - panic(err) - } + span.SetAttributes(attribute.String("variables", string(data))) - span.SetAttributes(attribute.String("variables", string(data))) + instance, triggerError := a.manager.RunWorkflow(ctx, trigger.WorkflowID, evaluated) + if triggerError != nil { + return triggerError + } - instance, err := a.manager.RunWorkflow(ctx, trigger.WorkflowID, evaluated) - if err != nil { - return err + occurrence.WorkflowInstanceID = pointer.For(instance.ID) + } else { + triggerError = temporal.NewNonRetryableApplicationError("unable to eval variables", "VARIABLES_EVAL", triggerError) + span.RecordError(triggerError) + occurrence.Error = pointer.For(triggerError.Error()) } - _, err = a.db.NewInsert(). - Model(pointer.For(NewTriggerOccurrence(request.MessageID, trigger.ID, instance.ID, request.Event))). + _, err := a.db.NewInsert(). + Model(pointer.For(occurrence)). On("CONFLICT (trigger_id, event_id) DO NOTHING"). Exec(ctx) + if err != nil { + sharedlogging.FromContext(ctx).Errorf("unable to save trigger occurrence: %s", err) + } - return err + return triggerError } func NewActivities(db *bun.DB, manager *workflow.WorkflowManager, expressionEvaluator *expressionEvaluator) Activities { diff --git a/ee/orchestration/internal/triggers/trigger.go b/ee/orchestration/internal/triggers/trigger.go index 5c219aca57..ff5ab4b06c 100644 --- a/ee/orchestration/internal/triggers/trigger.go +++ b/ee/orchestration/internal/triggers/trigger.go @@ -102,18 +102,18 @@ type Occurrence struct { EventID string `json:"-" bun:"event_id,pk"` TriggerID string `json:"triggerID" bun:"trigger_id,pk"` - WorkflowInstanceID string `json:"workflowInstanceID" bun:"workflow_instance_id"` - WorkflowInstance workflow.Instance `json:"workflowInstance" bun:"rel:belongs-to,join:workflow_instance_id=id"` + WorkflowInstanceID *string `json:"workflowInstanceID,omitempty" bun:"workflow_instance_id"` + WorkflowInstance *workflow.Instance `json:"workflowInstance,omitempty" bun:"rel:belongs-to,join:workflow_instance_id=id"` Date time.Time `json:"date" bun:"date"` Event publish.EventMessage `json:"event" bun:"event"` + Error *string `json:"error,omitempty" bun:"error"` } -func NewTriggerOccurrence(eventID, triggerID, workflowInstanceID string, event publish.EventMessage) Occurrence { +func NewTriggerOccurrence(eventID, triggerID string, event publish.EventMessage) Occurrence { return Occurrence{ - TriggerID: triggerID, - EventID: eventID, - WorkflowInstanceID: workflowInstanceID, - Date: time.Now().Round(time.Microsecond).UTC(), - Event: event, + TriggerID: triggerID, + EventID: eventID, + Date: time.Now().Round(time.Microsecond).UTC(), + Event: event, } } diff --git a/ee/orchestration/internal/triggers/workflow_trigger.go b/ee/orchestration/internal/triggers/workflow_trigger.go index 6efeb566e2..1415bb6381 100644 --- a/ee/orchestration/internal/triggers/workflow_trigger.go +++ b/ee/orchestration/internal/triggers/workflow_trigger.go @@ -3,6 +3,9 @@ package triggers import ( "time" + "github.com/pkg/errors" + "go.temporal.io/sdk/temporal" + "github.com/formancehq/stack/libs/go-libs/publish" "github.com/uptrace/bun" temporalworkflow "go.temporal.io/sdk/workflow" @@ -42,7 +45,10 @@ func (w triggerWorkflow) RunTrigger(ctx temporalworkflow.Context, req ProcessEve req, ).Get(ctx, nil) if err != nil { - return err + applicationError := &temporal.ApplicationError{} + if !errors.As(err, &applicationError) { + return err + } } } diff --git a/ee/orchestration/openapi.yaml b/ee/orchestration/openapi.yaml index 27bfaa23b0..e2c04663b9 100644 --- a/ee/orchestration/openapi.yaml +++ b/ee/orchestration/openapi.yaml @@ -465,6 +465,35 @@ paths: $ref: '#/components/responses/V2ErrorResponse' default: $ref: '#/components/responses/V2ErrorResponse' + /v2/triggers/{triggerID}/test: + parameters: + - name: triggerID + description: The trigger id + in: path + schema: + type: string + required: true + post: + summary: Test trigger + operationId: testTrigger + description: Test trigger + tags: + - Orchestration + requestBody: + content: + application/json: + schema: + type: object + additionalProperties: true + responses: + "200": + description: Test a trigger + content: + application/json: + schema: + $ref: '#/components/schemas/V2TestTriggerResponse' + default: + $ref: '#/components/responses/V2ErrorResponse' /v2/triggers/{triggerID}/occurrences: parameters: - name: triggerID @@ -779,6 +808,7 @@ components: enum: - VALIDATION - NOT_FOUND + - INTERNAL errorMessage: type: string WorkflowConfig: @@ -964,6 +994,7 @@ components: required: - triggerID - workflowInstanceID + - workflowInstance - date - event properties: @@ -972,6 +1003,8 @@ components: format: date-time workflowInstanceID: type: string + workflowInstance: + $ref: '#/components/schemas/WorkflowInstance' triggerID: type: string event: @@ -1067,11 +1100,11 @@ components: $ref: '#/components/schemas/WorkflowInstanceHistoryStageList' StageSendSourceWallet: type: object + required: + - id properties: id: type: string - name: - type: string balance: type: string StageSendDestinationWallet: @@ -1181,6 +1214,74 @@ components: order_id: "6735" ActivityStripeTransfer: $ref: '#/components/schemas/StripeTransferRequest' + ActivityListWallets: + type: object + properties: + name: + type: string + ActivityListWalletsOutput: + $ref: '#/components/schemas/ListWalletsResponse' + ListWalletsResponse: + type: object + required: + - cursor + properties: + cursor: + allOf: + - $ref: '#/components/schemas/Cursor' + - properties: + data: + items: + $ref: '#/components/schemas/Wallet' + type: array + type: object + required: + - data + Wallet: + type: object + required: + - name + - id + - metadata + - createdAt + - ledger + properties: + id: + type: string + format: uuid + description: The unique ID of the wallet. + metadata: + type: object + additionalProperties: + type: string + description: Metadata associated with the wallet. + name: + type: string + createdAt: + type: string + format: date-time + ledger: + type: string + Cursor: + type: object + required: + - pageSize + properties: + pageSize: + type: integer + format: int64 + minimum: 1 + maximum: 1000 + example: 15 + hasMore: + type: boolean + example: false + previous: + type: string + example: YXVsdCBhbmQgYSBtYXhpbXVtIG1heF9yZXN1bHRzLol= + next: + type: string + example: "" ActivityGetAccount: type: object required: @@ -1198,6 +1299,16 @@ components: type: string data: $ref: '#/components/schemas/PostTransaction' + ActivityRevertTransaction: + type: object + required: + - id + - ledger + properties: + ledger: + type: string + id: + type: string ActivityGetPayment: type: object required: @@ -1326,13 +1437,6 @@ components: properties: id: type: string - ActivityListWallets: - type: object - properties: - name: - type: string - ActivityListWalletsOutput: - $ref: '#/components/schemas/ListWalletsResponse' ActivityVoidHold: type: object required: @@ -1370,11 +1474,18 @@ components: type: integer format: bigint minimum: 0 + reverted: + type: boolean required: - postings - timestamp - id - metadata + - reverted + ActivityRevertTransactionOutput: + $ref: '#/components/schemas/RevertTransactionResponse' + RevertTransactionResponse: + $ref: '#/components/schemas/CreateTransactionResponse' ActivityGetPaymentOutput: $ref: '#/components/schemas/PaymentResponse' PaymentResponse: @@ -1606,6 +1717,8 @@ components: $ref: '#/components/schemas/ActivityGetAccount' CreateTransaction: $ref: '#/components/schemas/ActivityCreateTransaction' + RevertTransaction: + $ref: '#/components/schemas/ActivityRevertTransaction' StripeTransfer: $ref: '#/components/schemas/ActivityStripeTransfer' GetPayment: @@ -1629,6 +1742,8 @@ components: $ref: '#/components/schemas/ActivityGetAccountOutput' CreateTransaction: $ref: '#/components/schemas/ActivityCreateTransactionOutput' + RevertTransaction: + $ref: '#/components/schemas/ActivityRevertTransactionOutput' GetPayment: $ref: '#/components/schemas/ActivityGetPaymentOutput' DebitWallet: @@ -1782,67 +1897,6 @@ components: input: 100 output: 10 balance: 90 - Cursor: - type: object - required: - - pageSize - properties: - pageSize: - type: integer - format: int64 - minimum: 1 - maximum: 1000 - example: 15 - hasMore: - type: boolean - example: false - previous: - type: string - example: "YXVsdCBhbmQgYSBtYXhpbXVtIG1heF9yZXN1bHRzLol=" - next: - type: string - example: "" - Wallet: - type: object - required: - - name - - id - - metadata - - createdAt - - ledger - properties: - id: - type: string - format: uuid - description: The unique ID of the wallet. - metadata: - type: object - additionalProperties: - type: string - description: Metadata associated with the wallet. - name: - type: string - createdAt: - type: string - format: date-time - ledger: - type: string - ListWalletsResponse: - type: object - required: - - cursor - properties: - cursor: - allOf: - - $ref: '#/components/schemas/Cursor' - - properties: - data: - items: - $ref: '#/components/schemas/Wallet' - type: array - type: object - required: - - data V2ServerInfo: type: object required: @@ -1861,6 +1915,7 @@ components: enum: - VALIDATION - NOT_FOUND + - INTERNAL errorMessage: type: string V2WorkflowConfig: @@ -2067,8 +2122,6 @@ components: type: object required: - triggerID - - workflowInstanceID - - workflowInstance - date - event properties: @@ -2081,6 +2134,8 @@ components: $ref: '#/components/schemas/V2WorkflowInstance' triggerID: type: string + error: + type: string event: type: object additionalProperties: true @@ -2302,6 +2357,10 @@ components: $ref: '#/components/schemas/V2StageSendDestination' source: $ref: '#/components/schemas/V2StageSendSource' + metadata: + type: object + additionalProperties: + type: string V2StageDelay: type: object properties: @@ -2351,33 +2410,91 @@ components: order_id: "6735" V2ActivityStripeTransfer: $ref: '#/components/schemas/V2StripeTransferRequest' - V2ActivityGetAccount: + V2ActivityListWallets: + type: object + properties: + name: + type: string + V2ActivityListWalletsOutput: + $ref: '#/components/schemas/V2ListWalletsResponse' + V2ListWalletsResponse: + type: object + required: + - cursor + properties: + cursor: + allOf: + - $ref: '#/components/schemas/V2Cursor' + - properties: + data: + items: + $ref: '#/components/schemas/V2Wallet' + type: array + type: object + required: + - data + V2Wallet: type: object required: + - name - id + - metadata + - createdAt - ledger properties: id: type: string + format: uuid + description: The unique ID of the wallet. + metadata: + type: object + additionalProperties: + type: string + description: Metadata associated with the wallet. + name: + type: string + createdAt: + type: string + format: date-time ledger: type: string - V2ActivityCreateTransaction: + V2Cursor: type: object + required: + - pageSize properties: - ledger: + pageSize: + type: integer + format: int64 + minimum: 1 + maximum: 1000 + example: 15 + hasMore: + type: boolean + example: false + previous: type: string - data: - $ref: '#/components/schemas/V2PostTransaction' - V2ActivityRevertTransaction: + example: YXVsdCBhbmQgYSBtYXhpbXVtIG1heF9yZXN1bHRzLol= + next: + type: string + example: "" + V2ActivityGetAccount: type: object required: - id - ledger properties: + id: + type: string ledger: type: string - id: + V2ActivityCreateTransaction: + type: object + properties: + ledger: type: string + data: + $ref: '#/components/schemas/V2PostTransaction' V2ActivityGetPayment: type: object required: @@ -2520,7 +2637,9 @@ components: V2CreateTransactionResponse: properties: data: - $ref: '#/components/schemas/V2Transaction' + type: array + items: + $ref: '#/components/schemas/V2Transaction' type: object required: - data @@ -2539,19 +2658,15 @@ components: example: ref:001 metadata: $ref: '#/components/schemas/V2Metadata' - id: + txid: type: integer format: bigint minimum: 0 required: - postings - timestamp - - id + - txid - metadata - V2ActivityRevertTransactionOutput: - $ref: '#/components/schemas/V2RevertTransactionResponse' - V2RevertTransactionResponse: - $ref: '#/components/schemas/V2CreateTransactionResponse' V2ActivityGetPaymentOutput: $ref: '#/components/schemas/V2PaymentResponse' V2PaymentResponse: @@ -2797,6 +2912,8 @@ components: $ref: '#/components/schemas/V2ActivityGetWallet' VoidHold: $ref: '#/components/schemas/V2ActivityVoidHold' + ListWallets: + $ref: '#/components/schemas/V2ActivityListWallets' V2WorkflowInstanceHistoryStageOutput: type: object properties: @@ -2810,6 +2927,8 @@ components: $ref: '#/components/schemas/V2ActivityDebitWalletOutput' GetWallet: $ref: '#/components/schemas/V2ActivityGetWalletOutput' + ListWallets: + $ref: '#/components/schemas/V2ListWalletsResponse' V2Monetary: type: object required: @@ -2955,6 +3074,32 @@ components: input: 100 output: 10 balance: 90 + V2TestTriggerResponse: + type: object + required: + - data + properties: + data: + $ref: '#/components/schemas/V2TriggerTest' + V2TriggerTest: + type: object + properties: + filter: + type: object + properties: + match: + type: boolean + error: + type: string + variables: + type: object + additionalProperties: + type: object + properties: + value: + type: string + error: + type: string responses: ErrorResponse: description: General error @@ -2962,7 +3107,6 @@ components: application/json: schema: $ref: '#/components/schemas/Error' - V2ErrorResponse: description: General error content: diff --git a/ee/orchestration/openapi/v1.yaml b/ee/orchestration/openapi/v1.yaml index f91a1c9bfc..6c64799d7d 100644 --- a/ee/orchestration/openapi/v1.yaml +++ b/ee/orchestration/openapi/v1.yaml @@ -594,8 +594,6 @@ components: type: object required: - triggerID - - workflowInstanceID - - workflowInstance - date - event properties: @@ -611,6 +609,8 @@ components: event: type: object additionalProperties: true + error: + type: string ListTriggersOccurrencesResponse: type: object properties: diff --git a/ee/orchestration/openapi/v2.yaml b/ee/orchestration/openapi/v2.yaml index 91b7f9cfdd..0b3fadf862 100644 --- a/ee/orchestration/openapi/v2.yaml +++ b/ee/orchestration/openapi/v2.yaml @@ -659,8 +659,6 @@ components: type: object required: - triggerID - - workflowInstanceID - - workflowInstance - date - event properties: @@ -673,6 +671,8 @@ components: $ref: '#/components/schemas/V2WorkflowInstance' triggerID: type: string + error: + type: string event: type: object additionalProperties: true diff --git a/releases/sdks/go/.speakeasy/gen.lock b/releases/sdks/go/.speakeasy/gen.lock index 6ba2b00d63..1c1ffcd6ba 100755 --- a/releases/sdks/go/.speakeasy/gen.lock +++ b/releases/sdks/go/.speakeasy/gen.lock @@ -1,7 +1,7 @@ lockVersion: 2.0.0 id: 7eac0a45-60a2-40bb-9e85-26bd77ec2a6d management: - docChecksum: c333ef5c7396d3980e1a5806c46d1862 + docChecksum: 856389c2a0799eda0ac2db88971c6bf1 docVersion: v0.0.0 speakeasyVersion: internal generationVersion: 2.237.2 diff --git a/releases/sdks/go/docs/pkg/models/shared/triggeroccurrence.md b/releases/sdks/go/docs/pkg/models/shared/triggeroccurrence.md index 9daba66d7d..fad6049e30 100644 --- a/releases/sdks/go/docs/pkg/models/shared/triggeroccurrence.md +++ b/releases/sdks/go/docs/pkg/models/shared/triggeroccurrence.md @@ -3,10 +3,11 @@ ## Fields -| Field | Type | Required | Description | -| ------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------- | -| `Date` | [time.Time](https://pkg.go.dev/time#Time) | :heavy_check_mark: | N/A | -| `Event` | map[string]*interface{}* | :heavy_check_mark: | N/A | -| `TriggerID` | *string* | :heavy_check_mark: | N/A | -| `WorkflowInstance` | [shared.WorkflowInstance](../../../pkg/models/shared/workflowinstance.md) | :heavy_check_mark: | N/A | -| `WorkflowInstanceID` | *string* | :heavy_check_mark: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | -------------------------------------------------------------------------- | +| `Date` | [time.Time](https://pkg.go.dev/time#Time) | :heavy_check_mark: | N/A | +| `Error` | **string* | :heavy_minus_sign: | N/A | +| `Event` | map[string]*interface{}* | :heavy_check_mark: | N/A | +| `TriggerID` | *string* | :heavy_check_mark: | N/A | +| `WorkflowInstance` | [*shared.WorkflowInstance](../../../pkg/models/shared/workflowinstance.md) | :heavy_minus_sign: | N/A | +| `WorkflowInstanceID` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/releases/sdks/go/docs/pkg/models/shared/v2triggeroccurrence.md b/releases/sdks/go/docs/pkg/models/shared/v2triggeroccurrence.md index ba4882bc28..d596f4a82d 100644 --- a/releases/sdks/go/docs/pkg/models/shared/v2triggeroccurrence.md +++ b/releases/sdks/go/docs/pkg/models/shared/v2triggeroccurrence.md @@ -3,10 +3,11 @@ ## Fields -| Field | Type | Required | Description | -| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -| `Date` | [time.Time](https://pkg.go.dev/time#Time) | :heavy_check_mark: | N/A | -| `Event` | map[string]*interface{}* | :heavy_check_mark: | N/A | -| `TriggerID` | *string* | :heavy_check_mark: | N/A | -| `WorkflowInstance` | [shared.V2WorkflowInstance](../../../pkg/models/shared/v2workflowinstance.md) | :heavy_check_mark: | N/A | -| `WorkflowInstanceID` | *string* | :heavy_check_mark: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | +| `Date` | [time.Time](https://pkg.go.dev/time#Time) | :heavy_check_mark: | N/A | +| `Error` | **string* | :heavy_minus_sign: | N/A | +| `Event` | map[string]*interface{}* | :heavy_check_mark: | N/A | +| `TriggerID` | *string* | :heavy_check_mark: | N/A | +| `WorkflowInstance` | [*shared.V2WorkflowInstance](../../../pkg/models/shared/v2workflowinstance.md) | :heavy_minus_sign: | N/A | +| `WorkflowInstanceID` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/releases/sdks/go/pkg/models/shared/triggeroccurrence.go b/releases/sdks/go/pkg/models/shared/triggeroccurrence.go index 95b9fe3392..b4da648c14 100644 --- a/releases/sdks/go/pkg/models/shared/triggeroccurrence.go +++ b/releases/sdks/go/pkg/models/shared/triggeroccurrence.go @@ -9,10 +9,11 @@ import ( type TriggerOccurrence struct { Date time.Time `json:"date"` + Error *string `json:"error,omitempty"` Event map[string]interface{} `json:"event"` TriggerID string `json:"triggerID"` - WorkflowInstance WorkflowInstance `json:"workflowInstance"` - WorkflowInstanceID string `json:"workflowInstanceID"` + WorkflowInstance *WorkflowInstance `json:"workflowInstance,omitempty"` + WorkflowInstanceID *string `json:"workflowInstanceID,omitempty"` } func (t TriggerOccurrence) MarshalJSON() ([]byte, error) { @@ -33,6 +34,13 @@ func (o *TriggerOccurrence) GetDate() time.Time { return o.Date } +func (o *TriggerOccurrence) GetError() *string { + if o == nil { + return nil + } + return o.Error +} + func (o *TriggerOccurrence) GetEvent() map[string]interface{} { if o == nil { return map[string]interface{}{} @@ -47,16 +55,16 @@ func (o *TriggerOccurrence) GetTriggerID() string { return o.TriggerID } -func (o *TriggerOccurrence) GetWorkflowInstance() WorkflowInstance { +func (o *TriggerOccurrence) GetWorkflowInstance() *WorkflowInstance { if o == nil { - return WorkflowInstance{} + return nil } return o.WorkflowInstance } -func (o *TriggerOccurrence) GetWorkflowInstanceID() string { +func (o *TriggerOccurrence) GetWorkflowInstanceID() *string { if o == nil { - return "" + return nil } return o.WorkflowInstanceID } diff --git a/releases/sdks/go/pkg/models/shared/v2triggeroccurrence.go b/releases/sdks/go/pkg/models/shared/v2triggeroccurrence.go index 5d58d2f862..e164f19da1 100644 --- a/releases/sdks/go/pkg/models/shared/v2triggeroccurrence.go +++ b/releases/sdks/go/pkg/models/shared/v2triggeroccurrence.go @@ -9,10 +9,11 @@ import ( type V2TriggerOccurrence struct { Date time.Time `json:"date"` + Error *string `json:"error,omitempty"` Event map[string]interface{} `json:"event"` TriggerID string `json:"triggerID"` - WorkflowInstance V2WorkflowInstance `json:"workflowInstance"` - WorkflowInstanceID string `json:"workflowInstanceID"` + WorkflowInstance *V2WorkflowInstance `json:"workflowInstance,omitempty"` + WorkflowInstanceID *string `json:"workflowInstanceID,omitempty"` } func (v V2TriggerOccurrence) MarshalJSON() ([]byte, error) { @@ -33,6 +34,13 @@ func (o *V2TriggerOccurrence) GetDate() time.Time { return o.Date } +func (o *V2TriggerOccurrence) GetError() *string { + if o == nil { + return nil + } + return o.Error +} + func (o *V2TriggerOccurrence) GetEvent() map[string]interface{} { if o == nil { return map[string]interface{}{} @@ -47,16 +55,16 @@ func (o *V2TriggerOccurrence) GetTriggerID() string { return o.TriggerID } -func (o *V2TriggerOccurrence) GetWorkflowInstance() V2WorkflowInstance { +func (o *V2TriggerOccurrence) GetWorkflowInstance() *V2WorkflowInstance { if o == nil { - return V2WorkflowInstance{} + return nil } return o.WorkflowInstance } -func (o *V2TriggerOccurrence) GetWorkflowInstanceID() string { +func (o *V2TriggerOccurrence) GetWorkflowInstanceID() *string { if o == nil { - return "" + return nil } return o.WorkflowInstanceID } diff --git a/tests/integration/suite/orchestration-triggers.go b/tests/integration/suite/orchestration-triggers.go index 36c82a9c71..6f47e1c0f0 100644 --- a/tests/integration/suite/orchestration-triggers.go +++ b/tests/integration/suite/orchestration-triggers.go @@ -127,7 +127,7 @@ var _ = WithModules([]*Module{modules.Auth, modules.Orchestration, modules.Ledge var getInstanceResponse *operations.V2GetInstanceResponse Eventually(func() bool { getInstanceResponse, err = Client().Orchestration.V2GetInstance(TestContext(), operations.V2GetInstanceRequest{ - InstanceID: listTriggersOccurrencesResponse.V2ListTriggersOccurrencesResponse.Cursor.Data[0].WorkflowInstanceID, + InstanceID: *listTriggersOccurrencesResponse.V2ListTriggersOccurrencesResponse.Cursor.Data[0].WorkflowInstanceID, }) Expect(err).To(BeNil()) @@ -167,3 +167,65 @@ var _ = WithModules([]*Module{modules.Auth, modules.Orchestration, modules.Ledge }) }) }) + +var _ = WithModules([]*Module{modules.Auth, modules.Orchestration}, func() { + When("creating a new workflow with a delay of 5s and a trigger on payments creation", func() { + var ( + createTriggerResponse *operations.CreateTriggerResponse + ) + BeforeEach(func() { + response, err := Client().Orchestration.CreateWorkflow( + TestContext(), + &shared.CreateWorkflowRequest{ + Name: ptr(uuid.NewString()), + Stages: []map[string]interface{}{{"delay": map[string]any{"duration": "5s"}}}, + }, + ) + Expect(err).ToNot(HaveOccurred()) + Expect(response.StatusCode).To(Equal(201)) + + createTriggerResponse, err = Client().Orchestration.CreateTrigger( + TestContext(), + &shared.TriggerData{ + Event: paymentsevents.EventTypeSavedPayments, + WorkflowID: response.CreateWorkflowResponse.Data.ID, + Vars: map[string]any{ + "fail": `link(event, "unknown").name`, + }, + }, + ) + Expect(err).ToNot(HaveOccurred()) + }) + Then("publishing a new empty payment", func() { + var payment map[string]any + BeforeEach(func() { + payment = map[string]any{ + "id": uuid.NewString(), + } + PublishPayments(publish.EventMessage{ + Date: time.Now(), + App: "payments", + Type: paymentsevents.EventTypeSavedPayments, + Payload: payment, + }) + }) + It("Should create a trigger workflow", func() { + var ( + listTriggersOccurrencesResponse *operations.V2ListTriggersOccurrencesResponse + err error + ) + Eventually(func(g Gomega) bool { + listTriggersOccurrencesResponse, err = Client().Orchestration.V2ListTriggersOccurrences(TestContext(), operations.V2ListTriggersOccurrencesRequest{ + TriggerID: createTriggerResponse.CreateTriggerResponse.Data.ID, + }) + g.Expect(err).To(BeNil()) + g.Expect(listTriggersOccurrencesResponse.V2ListTriggersOccurrencesResponse.Cursor.Data).NotTo(BeEmpty()) + occurrence := listTriggersOccurrencesResponse.V2ListTriggersOccurrencesResponse.Cursor.Data[0] + g.Expect(occurrence.WorkflowInstanceID).To(BeNil()) + g.Expect(occurrence.WorkflowInstance).To(BeNil()) + return true + }).Should(BeTrue()) + }) + }) + }) +})