mirror of
https://github.com/jhillyerd/inbucket.git
synced 2025-12-20 02:57:05 +00:00
lua: Init with config and pool (#321)
* lua: Intial impl with config and pool Signed-off-by: James Hillyerd <james@hillyerd.com>
This commit is contained in:
85
pkg/extension/luahost/lua.go
Normal file
85
pkg/extension/luahost/lua.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package luahost
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/inbucket/inbucket/pkg/config"
|
||||
"github.com/inbucket/inbucket/pkg/extension"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
lua "github.com/yuin/gopher-lua"
|
||||
"github.com/yuin/gopher-lua/parse"
|
||||
)
|
||||
|
||||
// Host of Lua extensions.
|
||||
type Host struct {
|
||||
Functions []string // Functions detected in lua script.
|
||||
extHost *extension.Host
|
||||
pool *statePool
|
||||
logContext zerolog.Context
|
||||
}
|
||||
|
||||
// New constructs a new Lua Host, pre-compiling the source.
|
||||
func New(conf config.Lua, extHost *extension.Host) (*Host, error) {
|
||||
scriptPath := conf.Path
|
||||
if scriptPath == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
logContext := log.With().Str("module", "lua")
|
||||
logger := logContext.Str("phase", "startup").Str("path", scriptPath).Logger()
|
||||
|
||||
// Pre-load, parse, and compile script.
|
||||
if fi, err := os.Stat(scriptPath); err != nil {
|
||||
logger.Info().Msg("Script file not found")
|
||||
return nil, nil
|
||||
} else if fi.IsDir() {
|
||||
return nil, fmt.Errorf("Lua script %v is a directory", scriptPath)
|
||||
}
|
||||
|
||||
logger.Info().Msg("Loading script")
|
||||
file, err := os.Open(scriptPath)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewFromReader(extHost, bufio.NewReader(file), scriptPath)
|
||||
}
|
||||
|
||||
// NewFromReader constructs a new Lua Host, loading Lua source from the provided reader.
|
||||
// The provided path is used in logging and error messages.
|
||||
func NewFromReader(extHost *extension.Host, r io.Reader, path string) (*Host, error) {
|
||||
logContext := log.With().Str("module", "lua")
|
||||
|
||||
// Pre-parse, and compile script.
|
||||
chunk, err := parse.Parse(r, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
proto, err := lua.Compile(chunk, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Build the pool and confirm LState is retrievable.
|
||||
pool := newStatePool(proto)
|
||||
h := &Host{extHost: extHost, pool: pool, logContext: logContext}
|
||||
if ls, err := pool.getState(); err == nil {
|
||||
// State creation works, put it back.
|
||||
pool.putState(ls)
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// CreateChannel creates a channel and places it into the named global variable
|
||||
// in newly created LStates.
|
||||
func (h *Host) CreateChannel(name string) chan lua.LValue {
|
||||
return h.pool.createChannel(name)
|
||||
}
|
||||
Reference in New Issue
Block a user