Skip to content

Commit dbb0602

Browse files
committed
Lua executor fixes
Previous release had to change the behavior of how script.Script was parsed. The change related on how the content of the script was saved. It didn't keep headers which caused issues at execution. These changes makes it we don't keep just the content but we pass around the script.Script struct around. This change should help with the execution speed a little as we don't have to parse the script on every execution. All stores now keep the parsed script internally. For most cases it doesn't affect the user but for the etcd store it will require to delete everything currently in etcd before reapplying with an updated version of msgscript-cli.
1 parent 62fba1d commit dbb0602

File tree

15 files changed

+239
-135
lines changed

15 files changed

+239
-135
lines changed

executor/executor.go

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7-
"os"
87
"sync"
98
"time"
109

@@ -89,15 +88,6 @@ func (e *NoScriptFoundError) Error() string {
8988
return "No script found for subject"
9089
}
9190

92-
func createTempFile(pattern string) (*os.File, error) {
93-
tmpFile, err := os.CreateTemp(os.TempDir(), pattern)
94-
if err != nil {
95-
return nil, fmt.Errorf("failed to create temp file: %w", err)
96-
}
97-
98-
return tmpFile, nil
99-
}
100-
10191
type Executor interface {
10292
HandleMessage(context.Context, *Message, ReplyFunc)
10393
Stop()

executor/lua_executor.go

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,30 +53,34 @@ func replyWithError(fields log.Fields, rf ReplyFunc, msg string, a ...any) {
5353
// HandleMessage receives a message, matches it to a Lua script, and executes the script in a new goroutine
5454
func (le *LuaExecutor) HandleMessage(ctx context.Context, msg *Message, rf ReplyFunc) {
5555
fields := log.Fields{
56-
"subject": msg.Subject,
56+
"subject": msg.Subject,
5757
"executor": "lua",
5858
}
5959

6060
// Look up the Lua script for the given subject
6161
scripts, err := le.store.GetScripts(ctx, msg.Subject)
62-
if err != nil || scripts == nil {
63-
replyWithError(fields, rf, "failed to get scripts for subject %s: %w", msg.Subject, err)
62+
if err != nil {
63+
replyWithError(fields, rf, "failed to get scripts for subject %s: %v", msg.Subject, err)
6464
return
6565
}
6666

67+
if scripts == nil {
68+
replyWithError(fields, rf, "no scripts found for subject %s", msg.Subject)
69+
}
70+
6771
errs := make(chan error, len(scripts))
6872
var wg sync.WaitGroup
6973
r := NewReply()
7074
// Loop through each scripts attached to the subject as there might be more than one
71-
for path, script := range scripts {
75+
for path, scr := range scripts {
7276
wg.Add(1)
7377

7478
ss := strings.Split(path, "/")
7579
name := ss[len(ss)-1]
7680
fields["path"] = name
7781

7882
// Run the Lua script in a separate goroutine to handle the message for each script
79-
go func(content []byte) {
83+
go func(scr *scriptLib.Script) {
8084
defer wg.Done()
8185

8286
tmp, err := os.MkdirTemp(os.TempDir(), "msgscript-lua-*s")
@@ -92,14 +96,7 @@ func (le *LuaExecutor) HandleMessage(ctx context.Context, msg *Message, rf Reply
9296
return
9397
}
9498

95-
// Read the script to get the headers (for the libraries for example)
96-
s, err := scriptLib.ReadString(string(content))
97-
if err != nil {
98-
errs <- fmt.Errorf("failed to read script: %w", err)
99-
return
100-
}
101-
102-
libs, err := le.store.LoadLibrairies(ctx, s.LibKeys)
99+
libs, err := le.store.LoadLibrairies(ctx, scr.LibKeys)
103100
if err != nil {
104101
errs <- fmt.Errorf("failed to read librairies: %w", err)
105102
return
@@ -117,7 +114,7 @@ func (le *LuaExecutor) HandleMessage(ctx context.Context, msg *Message, rf Reply
117114
}
118115
defer le.store.ReleaseLock(ctx, name)
119116

120-
log.WithFields(fields).WithField("isHTML", s.HTML).Debug("executing script")
117+
log.WithFields(fields).WithField("isHTML", scr.HTML).Debug("executing script")
121118

122119
L := lua.NewState()
123120
tctx, tcan := context.WithTimeout(le.ctx, MAX_LUA_RUNNING_TIME)
@@ -147,11 +144,11 @@ func (le *LuaExecutor) HandleMessage(ctx context.Context, msg *Message, rf Reply
147144
sb.Write(l)
148145
sb.WriteString("\n")
149146
}
150-
sb.Write(content)
147+
sb.Write(scr.Content)
151148
log.WithFields(fields).Debugf("script:\n%+s\n\n", sb.String())
152149

153150
res := &ScriptResult{
154-
IsHTML: s.HTML,
151+
IsHTML: scr.HTML,
155152
Headers: make(map[string]string),
156153
}
157154
if err := L.DoString(sb.String()); err != nil {
@@ -163,7 +160,7 @@ func (le *LuaExecutor) HandleMessage(ctx context.Context, msg *Message, rf Reply
163160
}
164161

165162
// Retrieve the result from the Lua state (assuming it's a string)
166-
if s.HTML {
163+
if scr.HTML {
167164
// If the message is set to return HTML, we pass 2 things to the fonction named after the HTTP
168165
// method received ex: POST(), GET()...
169166
// The 2 things are:
@@ -177,7 +174,7 @@ func (le *LuaExecutor) HandleMessage(ctx context.Context, msg *Message, rf Reply
177174
// - The body of the message
178175
le.executeRawMessage(fields, L, r, msg, res, name)
179176
}
180-
}(script)
177+
}(scr)
181178
}
182179
wg.Wait()
183180
log.WithField("subject", msg.Subject).Debugf("finished running %d scripts", len(scripts))

executor/nopodman_executor.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//go:build !podman
2+
// This is so that we can build without podman's dependancies
3+
4+
package executor
5+
6+
import (
7+
"context"
8+
9+
msgstore "github.com/numkem/msgscript/store"
10+
)
11+
12+
type noPodmanExecutor struct{}
13+
14+
func NewPodmanExecutor(c context.Context, store msgstore.ScriptStore) (Executor, error) {
15+
return &noPodmanExecutor{}, nil
16+
}
17+
18+
func (e *noPodmanExecutor) HandleMessage(ctx context.Context, msg *Message, rf ReplyFunc) {
19+
r := NewReply()
20+
r.Error = "msgscript wasn't built with podman support"
21+
rf(r)
22+
}
23+
24+
func (e *noPodmanExecutor) Stop() {}

executor/nowasm_executor.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//go:build !wasm
2+
// This is so that we can build without wasm's dependancies
3+
4+
package executor
5+
6+
import (
7+
"context"
8+
9+
"github.com/nats-io/nats.go"
10+
msgplugins "github.com/numkem/msgscript/plugins"
11+
msgstore "github.com/numkem/msgscript/store"
12+
)
13+
14+
type noWasmExecutor struct{}
15+
16+
func NewWasmExecutor(c context.Context, store msgstore.ScriptStore, plugins []msgplugins.PreloadFunc, nc *nats.Conn) Executor {
17+
return &noWasmExecutor{}
18+
}
19+
20+
func (e *noWasmExecutor) HandleMessage(ctx context.Context, msg *Message, rf ReplyFunc) {
21+
r := NewReply()
22+
r.Error = "msgscript wasn't built with wasm support"
23+
rf(r)
24+
}
25+
26+
func (e *noWasmExecutor) Stop() {}

executor/executor_podman.go renamed to executor/podman_executor.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//go:build podman
2+
13
package executor
24

35
import (

executor/wasm_executor.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
//go:build wasm
2+
13
package executor
24

35
import (
6+
"context"
47
"encoding/json"
58
"fmt"
69
"io"
@@ -14,7 +17,6 @@ import (
1417
scriptLib "github.com/numkem/msgscript/script"
1518
msgstore "github.com/numkem/msgscript/store"
1619
log "github.com/sirupsen/logrus"
17-
"golang.org/x/net/context"
1820
)
1921

2022
type WasmExecutor struct {
@@ -56,8 +58,8 @@ func (we *WasmExecutor) HandleMessage(ctx context.Context, msg *Message, rf Repl
5658
ss := strings.Split(path, "/")
5759
name := ss[len(ss)-1]
5860
fields := log.Fields{
59-
"subject": msg.Subject,
60-
"path": name,
61+
"subject": msg.Subject,
62+
"path": name,
6163
"executor": "wasm",
6264
}
6365

@@ -199,4 +201,3 @@ func (we *WasmExecutor) Stop() {
199201
we.cancelFunc()
200202
log.Debug("WasmExecutor stopped")
201203
}
202-

flake.nix

Lines changed: 18 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,8 @@
88
outputs =
99
{ self, nixpkgs }:
1010
let
11-
version = "0.5.0";
12-
vendorHash = "sha256-LcgdJIsn3/fHv3NGvGdfq/Y3N7CTuIH/b5Rv5tEMUg8=";
13-
14-
mkCli =
15-
pkgs:
16-
let
17-
wasmtime = pkgs.callPackage ./nix/pkgs/wasmtime.nix { };
18-
in
19-
pkgs.buildGoModule {
20-
pname = "msgscript-cli";
21-
inherit version vendorHash;
22-
23-
src = self;
24-
25-
subPackages = [ "cmd/cli" ];
26-
27-
nativeBuildInputs = [ pkgs.pkg-config ];
28-
29-
buildInputs = [
30-
wasmtime.dev
31-
pkgs.btrfs-progs
32-
pkgs.gpgme
33-
];
34-
35-
postInstall = ''
36-
mv $out/bin/cli $out/bin/msgscriptcli
37-
'';
38-
};
39-
40-
mkServer =
41-
pkgs:
42-
let
43-
wasmtime = pkgs.callPackage ./nix/pkgs/wasmtime.nix { };
44-
in
45-
pkgs.buildGoModule {
46-
pname = "msgscript";
47-
inherit version vendorHash;
48-
49-
src = self;
50-
51-
subPackages = [ "cmd/server" ];
52-
53-
nativeBuildInputs = [ pkgs.pkg-config ];
54-
55-
buildInputs = [
56-
wasmtime.dev
57-
pkgs.btrfs-progs
58-
pkgs.gpgme
59-
];
60-
61-
doCheck = false; # Requires networking, will just timeout
62-
63-
postInstall = ''
64-
mv $out/bin/server $out/bin/msgscript
65-
'';
66-
};
11+
version = "0.6.0";
12+
vendorHash = "sha256-+sI9iQsfaxPlVoQFCLDHGrl7VHgnq1iLOrRj57Fpudc=";
6713

6814
mkPlugin =
6915
pkgs: name: path:
@@ -94,10 +40,16 @@
9440
let
9541
pkgs = import nixpkgs { system = "x86_64-linux"; };
9642
lib = pkgs.lib;
43+
44+
wasmtime = pkgs.callPackage ./nix/pkgs/wasmtime.nix { };
9745
in
9846
rec {
99-
cli = mkCli pkgs;
100-
server = mkServer pkgs;
47+
cli = pkgs.callPackage ./nix/pkgs/cli.nix {
48+
inherit wasmtime version vendorHash;
49+
};
50+
server = pkgs.callPackage ./nix/pkgs/server.nix {
51+
inherit wasmtime version vendorHash;
52+
};
10153
default = server;
10254

10355
allPlugins = pkgs.symlinkJoin {
@@ -119,10 +71,16 @@
11971
let
12072
pkgs = import nixpkgs { system = "aarch64-linux"; };
12173
lib = pkgs.lib;
74+
75+
wasmtime = pkgs.callPackage ./nix/pkgs/wasmtime.nix { };
12276
in
12377
rec {
124-
cli = mkCli "x86_64-linux";
125-
server = mkServer "x86_64-linux";
78+
cli = pkgs.callPackage ./nix/pkgs/cli.nix {
79+
inherit wasmtime version vendorHash;
80+
};
81+
server = pkgs.callPackage ./nix/pkgs/server.nix {
82+
inherit wasmtime version vendorHash;
83+
};
12684
default = server;
12785

12886
allPlugins = pkgs.symlinkJoin {

nix/pkgs/cli.nix

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
lib,
3+
buildGoModule,
4+
btrfs-progs,
5+
gpgme,
6+
pkg-config,
7+
wasmtime,
8+
vendorHash,
9+
version,
10+
withPodman ? false,
11+
withWasm ? false,
12+
}:
13+
14+
buildGoModule {
15+
pname = "msgscript-cli";
16+
inherit version vendorHash;
17+
18+
src = ../..;
19+
20+
subPackages = [ "cmd/cli" ];
21+
22+
nativeBuildInputs = [ ] ++ (lib.optional withPodman [ pkg-config ]);
23+
24+
buildInputs =
25+
[ ]
26+
++ (lib.optional withWasm [ wasmtime.dev ])
27+
++ (lib.optional withPodman [
28+
btrfs-progs
29+
gpgme
30+
]);
31+
32+
postInstall = ''
33+
mv $out/bin/cli $out/bin/msgscriptcli
34+
'';
35+
}

nix/pkgs/server.nix

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
lib,
3+
buildGoModule,
4+
btrfs-progs,
5+
gpgme,
6+
pkg-config,
7+
wasmtime,
8+
vendorHash,
9+
version,
10+
withPodman ? false,
11+
withWasm ? false,
12+
}:
13+
14+
buildGoModule {
15+
pname = "msgscript";
16+
inherit version vendorHash;
17+
18+
src = ../..;
19+
20+
subPackages = [ "cmd/server" ];
21+
22+
nativeBuildInputs = [ pkg-config ];
23+
24+
buildInputs =
25+
[ ]
26+
++ (lib.optional withWasm [ wasmtime.dev ])
27+
++ (lib.optional withPodman [
28+
btrfs-progs
29+
gpgme
30+
]);
31+
32+
doCheck = false; # Requires networking, will just timeout
33+
34+
postInstall = ''
35+
mv $out/bin/server $out/bin/msgscript
36+
'';
37+
}

0 commit comments

Comments
 (0)