@@ -3,15 +3,66 @@ package redis
3
3
import (
4
4
"context"
5
5
"encoding/json"
6
+ "fmt"
6
7
"strconv"
7
8
8
9
"github.com/cschleiden/go-workflows/backend/history"
9
10
"github.com/cschleiden/go-workflows/core"
10
11
"github.com/redis/go-redis/v9"
11
12
)
12
13
14
+ type eventWithoutAttributes struct {
15
+ * history.Event
16
+ }
17
+
18
+ func (e * eventWithoutAttributes ) MarshalJSON () ([]byte , error ) {
19
+ return json .Marshal (& struct {
20
+ * history.Event
21
+ Attributes interface {} `json:"attr"`
22
+ }{
23
+ Event : e .Event ,
24
+ Attributes : nil ,
25
+ })
26
+ }
27
+
28
+ func marshalEventWithoutAttributes (event * history.Event ) (string , error ) {
29
+ data , err := json .Marshal (& eventWithoutAttributes {event })
30
+ if err != nil {
31
+ return "" , err
32
+ }
33
+
34
+ return string (data ), nil
35
+ }
36
+
37
+ // KEYS[1..n] - payload keys
38
+ // ARGV[1..n] - payload values
39
+ var addPayloadsCmd = redis .NewScript (`
40
+ for i = 1, #ARGV do
41
+ redis.pcall("SET", KEYS[i], ARGV[i], "NX")
42
+ end
43
+
44
+ return 0
45
+ ` )
46
+
47
+ func addEventPayloads (ctx context.Context , p redis.Pipeliner , events []* history.Event ) error {
48
+ keys := make ([]string , 0 )
49
+ values := make ([]interface {}, 0 )
50
+
51
+ for _ , event := range events {
52
+ payload , err := json .Marshal (event .Attributes )
53
+ if err != nil {
54
+ return fmt .Errorf ("marshaling event payload: %w" , err )
55
+ }
56
+
57
+ keys = append (keys , payloadKey (event .ID ))
58
+ values = append (values , string (payload ))
59
+ }
60
+
61
+ return addPayloadsCmd .Run (ctx , p , keys , values ... ).Err ()
62
+ }
63
+
13
64
func addEventToStreamP (ctx context.Context , p redis.Pipeliner , streamKey string , event * history.Event ) error {
14
- eventData , err := json . Marshal (event )
65
+ eventData , err := marshalEventWithoutAttributes (event )
15
66
if err != nil {
16
67
return err
17
68
}
@@ -37,10 +88,10 @@ var addEventsToStreamCmd = redis.NewScript(`
37
88
return msgID
38
89
` )
39
90
40
- func addEventsToHistoryStreamP (ctx context.Context , p redis.Pipeliner , streamKey string , events []* history.Event ) error {
91
+ func addEventsToStreamP (ctx context.Context , p redis.Pipeliner , streamKey string , events []* history.Event ) error {
41
92
eventsData := make ([]string , 0 )
42
93
for _ , event := range events {
43
- eventData , err := json . Marshal (event )
94
+ eventData , err := marshalEventWithoutAttributes (event )
44
95
if err != nil {
45
96
return err
46
97
}
@@ -56,37 +107,49 @@ func addEventsToHistoryStreamP(ctx context.Context, p redis.Pipeliner, streamKey
56
107
return nil
57
108
}
58
109
110
+ // Adds an event to be delivered in the future. Not cluster-safe.
59
111
// KEYS[1] - future event zset key
60
112
// KEYS[2] - future event key
113
+ // KEYS[3] - future event payload key
61
114
// ARGV[1] - timestamp
62
115
// ARGV[2] - Instance segment
63
- // ARGV[3] - event payload
116
+ // ARGV[3] - event data
117
+ // ARGV[4] - event payload
64
118
var addFutureEventCmd = redis .NewScript (`
65
119
redis.call("ZADD", KEYS[1], ARGV[1], KEYS[2])
66
- return redis.call("HSET", KEYS[2], "instance", ARGV[2], "event", ARGV[3])
120
+ redis.call("HSET", KEYS[2], "instance", ARGV[2], "event", ARGV[3], "payload", KEYS[3])
121
+ redis.call("SET", KEYS[3], ARGV[4], "NX")
122
+ return 0
67
123
` )
68
124
69
125
func addFutureEventP (ctx context.Context , p redis.Pipeliner , instance * core.WorkflowInstance , event * history.Event ) error {
70
- eventData , err := json . Marshal (event )
126
+ eventData , err := marshalEventWithoutAttributes (event )
71
127
if err != nil {
72
128
return err
73
129
}
74
130
75
- addFutureEventCmd .Run (
131
+ payloadEventData , err := json .Marshal (event .Attributes )
132
+ if err != nil {
133
+ return err
134
+ }
135
+
136
+ return addFutureEventCmd .Run (
76
137
ctx , p ,
77
- []string {futureEventsKey (), futureEventKey (instance , event .ScheduleEventID )},
138
+ []string {futureEventsKey (), futureEventKey (instance , event .ScheduleEventID ), payloadKey ( event . ID ) },
78
139
strconv .FormatInt (event .VisibleAt .UnixMilli (), 10 ),
79
140
instanceSegment (instance ),
80
141
string (eventData ),
81
- )
82
-
83
- return nil
142
+ string (payloadEventData ),
143
+ ).Err ()
84
144
}
85
145
146
+ // Remove a scheduled future event. Not cluster-safe.
86
147
// KEYS[1] - future event zset key
87
148
// KEYS[2] - future event key
88
149
var removeFutureEventCmd = redis .NewScript (`
89
150
redis.call("ZREM", KEYS[1], KEYS[2])
151
+ local k = redis.call("HGET", KEYS[2], "payload")
152
+ redis.call("DEL", k)
90
153
return redis.call("DEL", KEYS[2])
91
154
` )
92
155
0 commit comments