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  }