107 lines
2.3 KiB
Go
107 lines
2.3 KiB
Go
|
package data
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
"sync"
|
||
|
|
||
|
"git.tcp.direct/kayos/common/squish"
|
||
|
"git.tcp.direct/tcp.direct/database"
|
||
|
)
|
||
|
|
||
|
func kvMacros() database.Store {
|
||
|
return kv().With("macros")
|
||
|
}
|
||
|
|
||
|
type Macro struct {
|
||
|
Name string `json:"name"`
|
||
|
Description string `json:"description,omitempty"`
|
||
|
Sequence []string `json:"sequence"`
|
||
|
}
|
||
|
|
||
|
type macroCache struct {
|
||
|
cache map[string]*Macro
|
||
|
*sync.RWMutex
|
||
|
}
|
||
|
|
||
|
var macros = ¯oCache{
|
||
|
cache: make(map[string]*Macro),
|
||
|
RWMutex: new(sync.RWMutex),
|
||
|
}
|
||
|
|
||
|
func hasMacroCached(name string) *Macro {
|
||
|
macros.RLock()
|
||
|
defer macros.RUnlock()
|
||
|
if macroPtr, ok := macros.cache[name]; ok {
|
||
|
return macroPtr
|
||
|
}
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func unpackMacro(input []byte) (macro *Macro, err error) {
|
||
|
if input, err = squish.Gunzip(input); err != nil {
|
||
|
return nil, fmt.Errorf("error deflating macro: %w", err)
|
||
|
}
|
||
|
err = json.Unmarshal(input, ¯o)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func updateCache(name string, macro *Macro) {
|
||
|
macros.Lock()
|
||
|
macros.cache[name] = macro
|
||
|
macros.Unlock()
|
||
|
}
|
||
|
|
||
|
func GetMacro(name string) (mcro *Macro, err error) {
|
||
|
name = strings.ToLower(strings.TrimSpace(name))
|
||
|
if cached := hasMacroCached(name); cached != nil {
|
||
|
return cached, nil
|
||
|
}
|
||
|
|
||
|
if !kvMacros().Has([]byte(name)) {
|
||
|
|
||
|
}
|
||
|
|
||
|
var packed []byte
|
||
|
if packed, err = kvMacros().Get([]byte(name)); err != nil {
|
||
|
return nil, fmt.Errorf("error fetching macro: %w", err)
|
||
|
}
|
||
|
|
||
|
if mcro, err = unpackMacro(packed); err != nil {
|
||
|
return nil, fmt.Errorf("error unpacking macro: %w", err)
|
||
|
}
|
||
|
|
||
|
go updateCache(name, mcro)
|
||
|
|
||
|
return mcro, err
|
||
|
}
|
||
|
|
||
|
func DeleteMacro(name string) error {
|
||
|
macros.Lock()
|
||
|
defer macros.Unlock()
|
||
|
delete(macros.cache, name)
|
||
|
return fmt.Errorf(
|
||
|
"failed to delete macro: %w",
|
||
|
kvMacros().Delete([]byte(strings.ToLower(strings.TrimSpace(name)))),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
// AddMacro adds a macro to the database, the description is optional.
|
||
|
func AddMacro(name string, description string, sequence ...string) error {
|
||
|
if _, err := GetMacro(name); err == nil {
|
||
|
return fmt.Errorf("a macro named %q already exists", name)
|
||
|
}
|
||
|
mcro := Macro{
|
||
|
Name: name,
|
||
|
Description: description,
|
||
|
Sequence: sequence,
|
||
|
}
|
||
|
rawMacro, err := json.Marshal(mcro)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("failed to marshal macro: %w", err)
|
||
|
}
|
||
|
rawMacro = squish.Gzip(rawMacro)
|
||
|
return kvMacros().Put([]byte(strings.ToLower(strings.TrimSpace(name))), rawMacro)
|
||
|
}
|