// package local_ctx -- локальный контекст package local_ctx import ( "context" "fmt" "sync" "gitp78su.ipnodns.ru/svi/kern/v4/lev0/helpers" . "gitp78su.ipnodns.ru/svi/kern/v4/lev0/ktypes" "gitp78su.ipnodns.ru/svi/kern/v4/lev1/ctx_value" "gitp78su.ipnodns.ru/svi/kern/v4/lev1/log_buf" "gitp78su.ipnodns.ru/svi/kern/v4/lev1/lst_sort" . "gitp78su.ipnodns.ru/svi/kern/v4/lev1/option" . "gitp78su.ipnodns.ru/svi/kern/v4/lev1/result" ) // LocalCtx -- локальный контекст type LocalCtx struct { sync.RWMutex ctx context.Context // Отменяемый контекст fnCancel func() // Функция отмены контекста dictVal map[string]ICtxValue // Словарь различных значений lstSort *lst_sort.LstSort // Сортированный список значений log ILogBuf // Локальный буфер } // NewLocalCtx -- возвращает новый локальный контекст func NewLocalCtx(ctx context.Context) IResult[*LocalCtx] { if ctx == nil { err := fmt.Errorf("NewLocalCtx(): ctx==nil") return NewErr[*LocalCtx](err) } _ctx, fnCancel := context.WithCancel(ctx) sf := &LocalCtx{ ctx: _ctx, fnCancel: fnCancel, dictVal: map[string]ICtxValue{}, lstSort: lst_sort.NewLstSort(), log: log_buf.NewLogBuf(log_buf.OptIsTerm(true), log_buf.OptPrefix("LocalCtx")), } _ = ILocalCtx(sf) return NewRes(sf) } // Ctx -- возвращает отменяемый контекст func (sf *LocalCtx) Ctx() context.Context { return sf.ctx } // Size -- возвращает размер контекста func (sf *LocalCtx) Size() int { sf.RLock() defer sf.RUnlock() return len(sf.dictVal) } // SortedList -- возвращает сортированный список значений func (sf *LocalCtx) SortedList() []ICtxValue { return sf.lstSort.List() } // Log -- возвращает локальный буферный лог func (sf *LocalCtx) Log() ILogBuf { return sf.log } // Get -- возвращает хранимое значение func (sf *LocalCtx) Get(key string) IOption[ICtxValue] { sf.RLock() defer sf.RUnlock() if key == "" { return NewNone[ICtxValue]() } sf.log.Debug("Get(): key='%v'", key) val, isOk := sf.dictVal[key] if !isOk { return NewNone[ICtxValue]() } return NewOpt(val) } // Del -- удаляет значение из контекста func (sf *LocalCtx) Del(key string) { sf.Lock() defer sf.Unlock() sf.log.Debug("Del(): key='%v'", key) val := sf.dictVal[key] delete(sf.dictVal, key) sf.lstSort.Del(val) } // Set -- добавляет значение в контекст func (sf *LocalCtx) Set(key string, val any, comment string) IResult[bool] { sf.Lock() defer sf.Unlock() sf.log.Debug("Set(): key='%v'", key) _val, isOk := sf.dictVal[key] if isOk { val0 := _val.(*ctx_value.CtxValue) val0.Lock() val0.UpdateAt_ = helpers.TimeNowStr() val0.Val_ = val val0.Unlock() return NewRes(true) } resVal := ctx_value.NewCtxValue(key, val, comment) if resVal.IsErr() { return NewErr[bool](resVal.Err()) } _val = resVal.Val() sf.dictVal[key] = _val sf.lstSort.Add(_val) return NewRes(true) } // Wait -- блокирующий вызов ожидания отмены контекста func (sf *LocalCtx) Wait() { <-sf.ctx.Done() } // Cancel -- отменяет контекст func (sf *LocalCtx) Cancel() { sf.log.Warn("Cancel()") sf.fnCancel() }