1
0
forked from x/icebergs
icebergs/base/mdb/hash.go
2022-06-19 08:18:50 +08:00

248 lines
7.3 KiB
Go

package mdb
import (
"encoding/json"
"os"
"path"
ice "shylinux.com/x/icebergs"
kit "shylinux.com/x/toolkits"
)
func _hash_fields(m *ice.Message) []string {
return kit.Split(kit.Select("time,hash,type,name,text", m.OptionFields()))
}
func _hash_inputs(m *ice.Message, prefix, chain string, field, value string) {
list := map[string]int{}
m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) {
if val = kit.GetMeta(val); kit.Format(val[COUNT]) != "" {
list[kit.Format(val[field])] = kit.Int(val[COUNT])
} else {
list[kit.Format(val[field])]++
}
})
for k, i := range list {
m.Push(field, k)
m.Push(COUNT, i)
}
m.SortIntR(COUNT)
}
func _hash_insert(m *ice.Message, prefix, chain string, arg ...string) {
if m.Option(ice.MSG_DOMAIN) != "" {
m.Conf(prefix, kit.Keys(chain, kit.Keym(SHORT)), m.Conf(prefix, kit.Keym(SHORT)))
}
m.Log_INSERT(KEY, path.Join(prefix, chain), arg[0], arg[1])
if expire := m.Conf(prefix, kit.Keys(chain, kit.Keym(EXPIRE))); expire != "" {
arg = kit.Simple(TIME, m.Time(expire), arg)
}
m.Echo(m.Rich(prefix, chain, kit.Data(arg)))
}
func _hash_delete(m *ice.Message, prefix, chain, field, value string) {
if field != HASH {
field, value = HASH, kit.Select(kit.Hashs(value), m.Option(HASH))
}
m.Richs(prefix, chain, value, func(key string, val ice.Map) {
m.Log_DELETE(KEY, path.Join(prefix, chain), field, value, VALUE, kit.Format(val))
m.Conf(prefix, kit.Keys(chain, HASH, key), "")
})
}
func _hash_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) {
m.Richs(prefix, chain, value, func(key string, val ice.Map) {
val = kit.GetMeta(val)
m.Log_MODIFY(KEY, path.Join(prefix, chain), field, value, arg)
for i := 0; i < len(arg); i += 2 {
if arg[i] == field {
continue
}
kit.Value(val, arg[i], kit.Select("", arg, i+1))
}
})
}
func _hash_select(m *ice.Message, prefix, chain, field, value string) {
if field == HASH && value == RANDOM {
value = RANDOMS
}
fields := _hash_fields(m)
m.Richs(prefix, chain, value, func(key string, val ice.Map) {
switch val = kit.GetMeta(val); cb := m.OptionCB(SELECT).(type) {
case func(fields []string, value ice.Map):
cb(fields, val)
case func(value ice.Map):
cb(val)
default:
if m.OptionFields() == DETAIL {
m.Push(DETAIL, val)
} else {
m.Push(key, val, fields)
}
}
})
if !m.FieldsIsDetail() {
m.SortTimeR(TIME)
}
}
func _hash_export(m *ice.Message, prefix, chain, file string) {
f, p, e := kit.Create(kit.Keys(file, JSON))
m.Assert(e)
defer f.Close()
en := json.NewEncoder(f)
en.SetIndent("", " ")
m.Assert(en.Encode(m.Confv(prefix, kit.Keys(chain, HASH))))
m.Log_EXPORT(KEY, path.Join(prefix, chain), FILE, p)
m.Conf(prefix, kit.Keys(chain, HASH), "")
m.Echo(p)
}
func _hash_import(m *ice.Message, prefix, chain, file string) {
f, e := os.Open(kit.Keys(file, JSON))
if m.Warn(e) {
return
}
defer f.Close()
list := ice.Map{}
m.Assert(json.NewDecoder(f).Decode(&list))
count := 0
if m.Conf(prefix, kit.Keys(chain, META, SHORT)) == "" {
for k, data := range list {
m.Conf(prefix, kit.Keys(chain, HASH, k), data)
count++
}
} else {
for _, data := range list {
m.Rich(prefix, chain, data)
count++
}
}
m.Log_IMPORT(KEY, path.Join(prefix, chain), COUNT, count)
m.Echo("%d", count)
}
func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) {
fields := _hash_fields(m)
m.Richs(prefix, chain, FOREACH, func(key string, val ice.Map) {
switch val = kit.GetMeta(val); cb := m.OptionCB(PRUNES).(type) {
case func(string, ice.Map) bool:
if !cb(key, val) {
return
}
default:
for i := 0; i < len(arg)-1; i += 2 {
if val[arg[i]] != arg[i+1] && kit.Value(val, arg[i]) != arg[i+1] {
return
}
}
}
m.Push(key, val, fields)
})
m.Table(func(index int, value map[string]string, head []string) {
_hash_delete(m, prefix, chain, HASH, value[HASH])
})
}
const HASH = "hash"
func AutoConfig(args ...ice.Any) *ice.Action {
return &ice.Action{Hand: func(m *ice.Message, arg ...string) {
if cs := m.Target().Configs; cs[m.CommandKey()] == nil {
cs[m.CommandKey()] = &ice.Config{Value: kit.Data(args...)}
m.Load(m.CommandKey())
}
if cs := m.Target().Commands; cs[m.CommandKey()].Meta[CREATE] != nil {
return
}
inputs := []ice.Any{}
kit.Fetch(kit.Split(m.Config(FIELD)), func(i int, k string) {
switch k {
case TIME, HASH:
return
}
inputs = append(inputs, k)
})
m.Design(CREATE, "创建", inputs...)
}}
}
func HashAction(args ...ice.Any) map[string]*ice.Action {
_key := func(m *ice.Message) string {
if m.Config(HASH) == UNIQ {
return HASH
}
if m.Config(SHORT) == UNIQ {
return HASH
}
return kit.Select(HASH, m.Config(SHORT))
}
return ice.SelectAction(map[string]*ice.Action{ice.CTX_INIT: AutoConfig(args...),
INPUTS: {Name: "inputs", Help: "补全", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(INPUTS, m.PrefixKey(), "", HASH, arg)
}},
CREATE: {Name: "create", Help: "创建", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(INSERT, m.PrefixKey(), "", HASH, arg)
}},
REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(m.Config(FIELD))
m.Cmdy(DELETE, m.PrefixKey(), "", HASH, m.OptionSimple(_key(m)), arg)
m.Event(kit.Keys(m.CommandKey(), REMOVE), m.CommandKey(), m.Option(m.Config(SHORT)))
}},
MODIFY: {Name: "modify", Help: "编辑", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(MODIFY, m.PrefixKey(), "", HASH, m.OptionSimple(_key(m)), arg)
}},
EXPORT: {Name: "export", Help: "导出", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(m.Config(FIELD))
m.Cmdy(EXPORT, m.PrefixKey(), "", HASH, arg)
}},
IMPORT: {Name: "import", Help: "导入", Hand: func(m *ice.Message, arg ...string) {
m.Cmdy(IMPORT, m.PrefixKey(), "", HASH, arg)
}},
PRUNES: &ice.Action{Name: "prunes before@date", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
HashPrunes(m, nil)
}},
SELECT: &ice.Action{Name: "select hash auto", Help: "列表", Hand: func(m *ice.Message, arg ...string) {
HashSelect(m, arg...)
}},
})
}
func HashActionStatus(args ...ice.Any) map[string]*ice.Action {
list := HashAction(args...)
list[PRUNES] = &ice.Action{Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) {
m.OptionFields(m.Config(FIELD))
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, "error")
m.Cmdy(PRUNES, m.PrefixKey(), "", HASH, STATUS, "close")
}}
return list
}
func HashCreate(m *ice.Message, arg ...ice.Any) *ice.Message {
return m.Cmd(INSERT, m.PrefixKey(), "", HASH, kit.Simple(arg...))
}
func HashSelect(m *ice.Message, arg ...string) *ice.Message {
m.Fields(len(arg), m.Config(FIELD))
m.Cmdy(SELECT, m.PrefixKey(), "", HASH, m.Config(SHORT), arg)
m.PushAction(m.Config("action"), REMOVE)
m.StatusTimeCount()
return m
}
func HashPrunes(m *ice.Message, cb func(map[string]string) bool) *ice.Message {
_key := func(m *ice.Message) string {
if m.Config(HASH) == UNIQ {
return HASH
}
return kit.Select(HASH, m.Config(SHORT))
}
expire := kit.Time(kit.Select(m.Time("-72h"), m.Option(EXPIRE)))
m.Cmd(m.CommandKey()).Table(func(index int, value map[string]string, head []string) {
if kit.Time(value[TIME]) > expire {
return
}
if cb != nil && cb(value) {
return
}
m.OptionFields(m.Config(FIELD))
m.Cmdy(DELETE, m.PrefixKey(), "", HASH, _key(m), value[_key(m)])
})
return m
}