github.com/voedger/voedger@v0.0.0-20240520144910-273e84102129/pkg/sys/journal/impl_journal.go (about) 1 /* 2 * Copyright (c) 2021-present unTill Pro, Ltd. 3 */ 4 5 package journal 6 7 import ( 8 "context" 9 "errors" 10 "fmt" 11 "strings" 12 "time" 13 14 "github.com/voedger/voedger/pkg/appdef" 15 "github.com/voedger/voedger/pkg/extensionpoints" 16 "github.com/voedger/voedger/pkg/istructs" 17 "github.com/voedger/voedger/pkg/istructsmem" 18 "github.com/voedger/voedger/pkg/state" 19 coreutils "github.com/voedger/voedger/pkg/utils" 20 ) 21 22 func provideQryJournal(cfg *istructsmem.AppConfigType, ep extensionpoints.IExtensionPoint) { 23 cfg.Resources.Add(istructsmem.NewQueryFunction( 24 appdef.NewQName(appdef.SysPackage, "Journal"), 25 qryJournalExec(ep, cfg.AppDef), 26 )) 27 } 28 func qryJournalExec(ep extensionpoints.IExtensionPoint, appDef appdef.IAppDef) istructsmem.ExecQueryClosure { 29 return func(ctx context.Context, args istructs.ExecQueryArgs, callback istructs.ExecQueryCallback) (err error) { 30 var fo, lo int64 31 ji := ep.ExtensionPoint(EPJournalIndices) 32 jp := ep.ExtensionPoint(EPJournalPredicates) 33 switch args.ArgumentObject.AsString(field_RangeUnit) { 34 case rangeUnit_UnixTimestamp: 35 fallthrough 36 case "": 37 fo, lo, err = handleTimestamps(args.ArgumentObject, ji, args.State) 38 case rangeUnit_Offset: 39 fo, lo, err = handleOffsets(args.ArgumentObject) 40 default: 41 err = errArgumentTypeNotSupported 42 } 43 if err != nil { 44 return err 45 } 46 47 f, err := NewFilter(args.Workspace, strings.Split(args.ArgumentObject.AsString(Field_EventTypes), ","), jp) 48 if err != nil { 49 return err 50 } 51 52 cb := func(_ istructs.IKey, value istructs.IStateValue) (err error) { 53 if fo == int64(0) { 54 return 55 } 56 eo, err := NewEventObject(value.AsEvent("").(istructs.IWLogEvent), appDef, f, coreutils.WithNonNilsOnly()) 57 if err != nil { 58 return err 59 } 60 if !eo.Empty { 61 eo.Data[Field_Offset] = value.AsInt64(state.Field_Offset) 62 if err := callback(eo); err != nil { 63 return err 64 } 65 } 66 return err 67 } 68 69 kb, err := args.State.KeyBuilder(state.WLog, appdef.NullQName) 70 if err != nil { 71 return err 72 } 73 kb.PutInt64(state.Field_Offset, fo) 74 kb.PutInt64(state.Field_Count, lo-fo+1) 75 76 return args.State.Read(kb, cb) 77 } 78 } 79 func handleTimestamps(args istructs.IObject, epJornalIndices extensionpoints.IExtensionPoint, state istructs.IState) (fo, lo int64, err error) { 80 resetTime := func(milli int64) time.Time { 81 y, m, d := time.UnixMilli(milli).UTC().Date() 82 return time.Date(y, m, d, 0, 0, 0, 0, time.UTC) 83 } 84 85 from := resetTime(args.AsInt64(field_From)) 86 till := resetTime(args.AsInt64(field_Till)) 87 88 idxIntf, ok := epJornalIndices.Find(args.AsString(field_IndexForTimestamps)) 89 if !ok { 90 return 0, 0, errIndexNotSupported 91 } 92 idx := idxIntf.(appdef.QName) 93 94 return FindOffsetsByTimeRange(from, till, idx, state) 95 } 96 func handleOffsets(args istructs.IObject) (fo, lo int64, err error) { 97 fo = args.AsInt64(field_From) 98 lo = args.AsInt64(field_Till) 99 errs := make([]error, 0) 100 if fo <= 0 { 101 errs = append(errs, fmt.Errorf("'from' %w", errOffsetMustBePositive)) 102 } 103 if lo <= 0 { 104 errs = append(errs, fmt.Errorf("'till' %w", errOffsetMustBePositive)) 105 } 106 if fo > lo { 107 errs = append(errs, errFromOffsetMustBeLowerOrEqualToTillOffset) 108 } 109 err = errors.Join(errs...) 110 return 111 }