Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add bonzai.Persistence interface #276

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 79 additions & 9 deletions bonzai.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,15 @@ func (v Var) String() string {
// was not declared in [Cmd].Vars silently returns empty string.
func (x *Cmd) Get(key string) string {
v, has := x.vars[key]
if !has {
switch {
case !has:
return ""
}
if len(v.Env) > 0 {
case len(v.Env) > 0:
if val, has := os.LookupEnv(v.Env); has {
return val
}
case Persistence != nil && v.Persist:
return Persistence.Get(key)
}
return v.V
}
Expand All @@ -123,16 +125,17 @@ func (x *Cmd) Get(key string) string {
// string.
func (x *Cmd) Set(key, value string) {
v, has := x.vars[key]
if !has {
switch {
case !has:
return
}
v.V = value
if len(v.Env) > 0 {

case len(v.Env) > 0:
if _, has := os.LookupEnv(v.Env); has {
os.Setenv(v.Env, v.V)
os.Setenv(v.Env, value)
}
case Persistence != nil && v.Persist:
Persistence.Set(key, value)
}
v.V = value
}

// VarsSlice returns a slice with a copy of the current [Cmd].Vars. Use
Expand Down Expand Up @@ -176,6 +179,73 @@ type CmdCompleter interface {
SetCmd(x *Cmd)
}

// Persistence is used by [Cmd.Get] and [Cmd.Set] if not nil.
var Persistence Persister

func init() {
if Persistence != nil {
Persistence.Init()
}
}

// Persister interface specifies anything that implements
// a persistence layer for high-speed storage and retrieval of key/value
// combinations. Implementations may use whatever technology for
// persisting the data including simple files, key/value databases, API
// endpoints, or in-memory storage for applications where commands
// remain running beyond invocation.
//
// # Init
//
// Initialize a new persistence store if one does not yet exist. Must
// never clear or delete one that has been previously initialized.
// Usually this is called within an init() function after the other
// specific configurations of the driver have been set (much like
// database or other drivers).
//
// # Clear
//
// Clear removes all persistence (without disposing) restoring the
// persistent state to the same as before it was ever used historically.
// Most implementations will hold on to the same references created
// during [Init].
//
// # Get
//
// Get retrieves a value for a specific key in a case-sensitive way or
// returns an empty string if not found.
//
// # Set
//
// Set sets value for a given key. If the key does not exist, creates
// it and then sets. Otherwise, updates the value.
//
// # Delete
//
// Delete must delete a key from the persistent storage.
//
// # Best practices
//
// Usually it is best to keep driver implementation small and
// self-contained within its own package to enable the use of
// packaged-scoped variables during [init] when setting up the specifics
// of a particular driver implementation.
//
// Although the least amount of latency is preferred (generally
// sub-second) a driver makes no guarantees about the time it takes to
// perform any of the interface operations or even if they will ever
// complete at all. Latency requirements and timeouts must be managed
// externally.
type Persister interface {
CmdCompleter
Init() error
Clear() error
Has(key string) bool
Get(key string) string
Set(key, val string)
Delete(key string)
}

// Caller returns the internal reference to the parent/caller of this
// command. It is not set until [Cmd.Seek] is called or indirectly by
// [Cmd.Run] or [Cmd.Exec]. Caller is set to itself if there is no
Expand Down