-
Notifications
You must be signed in to change notification settings - Fork 20
/
legacy.go
123 lines (103 loc) · 3.33 KB
/
legacy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package runs
import (
"encoding/json"
"regexp"
"sort"
"strings"
"time"
"github.com/nyaruka/goflow/excellent/types"
"github.com/nyaruka/goflow/flows"
"github.com/nyaruka/goflow/utils"
)
var invalidLegacyExtraKeyChars = regexp.MustCompile(`[^a-zA-Z0-9_]`)
// keys in legacy @extra have non-word chars replaced with underscores and are limited to 255 chars
func legacyExtraKey(key string) string {
key = invalidLegacyExtraKeyChars.ReplaceAllString(strings.ToLower(key), "_")
return key[0:utils.MinInt(len(key), 255)]
}
type legacyExtraMap map[string]interface{}
func (e legacyExtraMap) Describe() string { return "legacy extra" }
func (e legacyExtraMap) ToXJSON(env utils.Environment) types.XText {
return types.MustMarshalToXText(e)
}
func (e legacyExtraMap) Reduce(env utils.Environment) types.XPrimitive { return e.ToXJSON(env) }
func (e legacyExtraMap) Resolve(env utils.Environment, key string) types.XValue {
key = strings.ToLower(key)
val, found := e[key]
if !found {
return types.NewXResolveError(e, key)
}
return e.convertToXValue(val)
}
func (e legacyExtraMap) convertToXValue(val interface{}) types.XValue {
switch typed := val.(type) {
case map[string]interface{}:
normalized := make(map[string]interface{}, len(typed))
for k, v := range typed {
normalized[legacyExtraKey(k)] = v
}
return legacyExtraMap(normalized)
case []interface{}:
xvals := make([]types.XValue, len(typed))
for v := range typed {
xvals[v] = e.convertToXValue(typed[v])
}
arr := types.NewXArray(xvals...)
return arr
case json.Number:
return types.RequireXNumberFromString(string(typed))
case string:
return types.NewXText(typed)
case bool:
return types.NewXBoolean(typed)
}
return nil
}
var _ types.XValue = (legacyExtraMap)(nil)
var _ types.XResolvable = (legacyExtraMap)(nil)
type legacyExtra struct {
legacyExtraMap
run flows.FlowRun
lastResultTime time.Time
}
func newLegacyExtra(run flows.FlowRun) *legacyExtra {
values := make(map[string]interface{})
// if trigger params is a JSON object, we include it in @extra
triggerParams := run.Session().Trigger().Params()
asJSON, isJSON := triggerParams.(types.XJSONObject)
if isJSON {
asMap, err := utils.JSONDecodeToMap(json.RawMessage(asJSON.XJSON))
if err == nil {
for k, v := range asMap {
values[legacyExtraKey(k)] = v
}
}
}
return &legacyExtra{legacyExtraMap: values, run: run}
}
// updates @legacy_extra by looking for new events since we last updated
func (e *legacyExtra) update() {
prevLastResultTime := e.lastResultTime
// get all results with extra created since the last update
newExtras := make([]*flows.Result, 0)
for _, result := range e.run.Results() {
if result.Extra != nil && result.CreatedOn.After(prevLastResultTime) {
newExtras = append(newExtras, result)
}
e.lastResultTime = result.CreatedOn
}
// sort by created time
sort.SliceStable(newExtras, func(i, j int) bool { return newExtras[i].CreatedOn.Before(newExtras[j].CreatedOn) })
// add each extra blob to our master extra
for _, result := range newExtras {
e.legacyExtraMap[utils.Snakify(result.Name)] = string(result.Extra)
values, err := utils.JSONDecodeToMap(result.Extra)
if err == nil {
for k, v := range values {
e.legacyExtraMap[legacyExtraKey(k)] = v
}
}
}
}
var _ types.XValue = (*legacyExtra)(nil)
var _ types.XResolvable = (*legacyExtra)(nil)