@@ -2,9 +2,13 @@ package function
2
2
3
3
import (
4
4
"encoding/json"
5
+ "errors"
5
6
"fmt"
7
+ "log"
8
+ "net/http"
6
9
"staticbackend/db"
7
10
"staticbackend/internal"
11
+ "time"
8
12
9
13
"github.com/dop251/goja"
10
14
"go.mongodb.org/mongo-driver/bson/primitive"
@@ -17,41 +21,89 @@ type ExecutionEnvironment struct {
17
21
Base * db.Base
18
22
Volatile internal.PubSuber
19
23
Data ExecData
24
+
25
+ CurrentRun ExecHistory
20
26
}
21
27
22
28
type Result struct {
23
29
OK bool `json:"ok"`
24
30
Content interface {} `json:"content"`
25
31
}
26
32
27
- func (env * ExecutionEnvironment ) Execute () error {
33
+ func (env * ExecutionEnvironment ) Execute (data interface {} ) error {
28
34
vm := goja .New ()
29
35
vm .SetFieldNameMapper (goja .TagFieldNameMapper ("json" , true ))
30
36
31
37
env .addHelpers (vm )
32
38
env .addDatabaseFunctions (vm )
33
39
env .addVolatileFunctions (vm )
34
40
35
- result , err := vm .RunString (env .Data .Code )
36
- if err != nil {
41
+ if _ , err := vm .RunString (env .Data .Code ); err != nil {
37
42
return err
38
43
}
39
44
40
45
handler , ok := goja .AssertFunction (vm .Get ("handle" ))
41
46
if ! ok {
42
- return fmt .Errorf (`unable to find function "handle": %v` , err )
47
+ return errors .New (`unable to find function "handle"` )
48
+ }
49
+
50
+ args , err := env .prepareArguments (vm , data )
51
+ if err != nil {
52
+ return fmt .Errorf ("error preparing argument: %v" , err )
53
+ }
54
+
55
+ env .CurrentRun = ExecHistory {
56
+ ID : primitive .NewObjectID ().Hex (),
57
+ Version : env .Data .Version ,
58
+ Started : time .Now (),
59
+ Output : make ([]string , 0 ),
43
60
}
44
61
45
- resp , err := handler (goja .Undefined ())
62
+ env .CurrentRun .Output = append (env .CurrentRun .Output , "Function started" )
63
+
64
+ _ , err = handler (goja .Undefined (), args ... )
65
+ go env .complete (err )
46
66
if err != nil {
47
67
return fmt .Errorf ("error executing your function: %v" , err )
48
68
}
49
69
50
- fmt .Println ("resp" , resp )
51
- fmt .Println ("result" , result )
52
70
return nil
53
71
}
54
72
73
+ func (env * ExecutionEnvironment ) prepareArguments (vm * goja.Runtime , data interface {}) ([]goja.Value , error ) {
74
+ var args []goja.Value
75
+
76
+ // for "web" trigger we prepare the body, query string and headers
77
+ r , ok := data .(* http.Request )
78
+ if ok {
79
+ defer r .Body .Close ()
80
+
81
+ // let's ready the HTTP body
82
+ if r .Header .Get ("Content-Type" ) == "application/json" {
83
+ var v interface {}
84
+ if err := json .NewDecoder (r .Body ).Decode (& v ); err != nil {
85
+ return nil , err
86
+ }
87
+
88
+ args = append (args , vm .ToValue (v ))
89
+ } else if r .Header .Get ("Content-Type" ) == "application/x-www-form-urlencoded" {
90
+ if err := r .ParseForm (); err != nil {
91
+ return nil , err
92
+ }
93
+ args = append (args , vm .ToValue (r .Form ))
94
+ }
95
+
96
+ args = append (args , vm .ToValue (r .URL .Query ()))
97
+ args = append (args , vm .ToValue (r .Header ))
98
+
99
+ return args , nil
100
+ }
101
+
102
+ // system or custom event/topic, we send only the 1st argument (body)
103
+ args = append (args , vm .ToValue (data ))
104
+ return args , nil
105
+ }
106
+
55
107
func (env * ExecutionEnvironment ) addHelpers (vm * goja.Runtime ) {
56
108
vm .Set ("log" , func (call goja.FunctionCall ) goja.Value {
57
109
if len (call .Arguments ) == 0 {
@@ -62,7 +114,7 @@ func (env *ExecutionEnvironment) addHelpers(vm *goja.Runtime) {
62
114
for _ , v := range call .Arguments {
63
115
params = append (params , v .Export ())
64
116
}
65
- fmt .Println (params ... )
117
+ env . CurrentRun . Output = append ( env . CurrentRun . Output , fmt .Sprint (params ... ) )
66
118
return goja .Undefined ()
67
119
})
68
120
}
@@ -292,3 +344,21 @@ func (env *ExecutionEnvironment) addVolatileFunctions(vm *goja.Runtime) {
292
344
return vm .ToValue (Result {OK : true })
293
345
})
294
346
}
347
+
348
+ func (env * ExecutionEnvironment ) complete (err error ) {
349
+ env .CurrentRun .Completed = time .Now ()
350
+ env .CurrentRun .Success = err == mongo .ErrNilCursor
351
+
352
+ env .CurrentRun .Output = append (env .CurrentRun .Output , "Function completed" )
353
+
354
+ // add the error in the last output entry
355
+ if err != nil {
356
+ env .CurrentRun .Output = append (env .CurrentRun .Output , err .Error ())
357
+ }
358
+
359
+ //TODO: this needs to be regrouped and ran un batch
360
+ if err := Ran (env .DB , env .Data .ID , env .CurrentRun ); err != nil {
361
+ //TODO: do something with those error
362
+ log .Println ("error logging function complete: " , err )
363
+ }
364
+ }
0 commit comments