sparse

package module
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 28, 2024 License: Apache-2.0 Imports: 8 Imported by: 1

README

go-sparse - Sparse series storage for Go

What this library can do?

  • Stores non-continuous segments of virtualy continuous data.
  • Can retrieve data for specific period, or answer if requested period is fully present.
  • Supports adding and updating periods and data entries to series.
  • Does NOT support deletion.
  • Merges periods which overlap or are conjuncted.
  • Can account of continuity of descrete keys (e.g. integers [1; 3] are followed by [4; 5] without gap between tham, which is not true for floats).
  • Supports empty periods.
  • Able to support any type of index.
  • Allows to implement any type of underlaying storage.

This library was created as base container for go-timeline.

Usage

Have some data with index field
type TestEvent struct {
   Time time.Time // In this case Time is index, but it could be anything
   Data int
}
Create sparse series
// Data storate factory
dataStorageFactory := sparse.NewArrayData[TestEvent, time.Time]

// Getter of index
getIdx := func(data *TestEvent) time.Time {
   return data.Time
}

// Comparator of index
cmp := func(idx1, idx2 time.Time) int {
   return idx1.Compare(idx2)
}

// Optional comparator to specify if index are continuous (so nothing can fit inbetween them)
areContinuous := func(smaller, bigger time.Time) bool {
   return smaller.UnixNano() == bigger.UnixNano()+1
}

series := sparse.NewSeries(dataStorageFactory, getIdx, cmp, areContinuous)
Add some data
// Adding period [1; 3]
series.AddData([]TestEvent{
   {Time: time.Unix(1, 0), Data: 1},
   {Time: time.Unix(2, 0), Data: 2},
   {Time: time.Unix(3, 0), Data: 3},
})

// Adding period [4; 6]
series.AddData([]TestEvent{
   {Time: time.Unix(4, 0), Data: 4},
   {Time: time.Unix(5, 0), Data: 5},
   {Time: time.Unix(6, 0), Data: 6},
})
Retrieve data from container
// Getting everything in range [1; 3), or [1; 2.000000005] if to be exact
res, err := series.Get(time.Unix(1, 0), time.Unix(2, 5))
require.NoError(t, err)
require.Equal(t, []TestEvent{
  {Time: time.Unix(1, 0), Data: 1},
  {Time: time.Unix(2, 0), Data: 2},
}, res)

Custom data storage

Indexed data may be stored in any type of storage - ArrayData is just an example of basic storage in memory. To support your own storage create implementation for SeriesData inteface and SeriesDataFactory function.

Examples

See folder examples or files *_test.go for more examples.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CompareNumber

func CompareNumber[ValType Number](a, b ValType) int

func CreateComparatorAny

func CreateComparatorAny[V any]() func(v1, v2 V) int

Types

type ArrayData

type ArrayData[Data any, Index any] struct {
	// contains filtered or unexported fields
}

func (*ArrayData[Data, Index]) First

func (s *ArrayData[Data, Index]) First(idx Index) (*Data, error)

func (*ArrayData[Data, Index]) Get

func (s *ArrayData[Data, Index]) Get(periodStart, periodEnd Index) ([]Data, error)

func (*ArrayData[Data, Index]) GetEndOpen

func (s *ArrayData[Data, Index]) GetEndOpen(periodStart, periodEnd Index) ([]Data, error)

func (*ArrayData[Data, Index]) Last

func (s *ArrayData[Data, Index]) Last(idx Index) (*Data, error)

func (*ArrayData[Data, Index]) Merge

func (s *ArrayData[Data, Index]) Merge(data []Data) error

func (*ArrayData[Data, Index]) String

func (s *ArrayData[Data, Index]) String() string

type MissingPeriodError

type MissingPeriodError[Index any] struct {
	PeriodStart Index
	PeriodEnd   Index
}

func (*MissingPeriodError[Index]) Error

func (e *MissingPeriodError[Index]) Error() string

type Number

type Number interface {
	constraints.Integer | constraints.Float
}

type PeriodBounds

type PeriodBounds[Index any] struct {
	PeriodStart Index
	PeriodEnd   Index
}

type Series

type Series[Data any, Index any] struct {
	// contains filtered or unexported fields
}

func NewSeries

func NewSeries[Data any, Index any](
	storageFactory SeriesDataFactory[Data, Index],
	getIdx func(data *Data) Index,
	cmp func(idx1, idx2 Index) int,
	areContinuous func(smaller, bigger Index) bool,
) *Series[Data, Index]

func (*Series[Data, Index]) AddData

func (s *Series[Data, Index]) AddData(data []Data) error

func (*Series[Data, Index]) AddPeriod

func (s *Series[Data, Index]) AddPeriod(periodStart, periodEnd Index, data []Data) error

func (*Series[Data, Index]) Get

func (s *Series[Data, Index]) Get(periodStart, periodEnd Index) ([]Data, error)

func (*Series[Data, Index]) GetAllSegments added in v1.0.1

func (s *Series[Data, Index]) GetAllSegments() []*SeriesSegment[Data, Index]

func (*Series[Data, Index]) GetPeriod

func (s *Series[Data, Index]) GetPeriod(periodStart, periodEnd Index) *SeriesSegment[Data, Index]

func (*Series[Data, Index]) GetPeriodClosestFromEnd

func (s *Series[Data, Index]) GetPeriodClosestFromEnd(t Index, nonEmpty bool) *SeriesSegment[Data, Index]

func (*Series[Data, Index]) GetPeriodClosestFromStart

func (s *Series[Data, Index]) GetPeriodClosestFromStart(t Index, nonEmpty bool) *SeriesSegment[Data, Index]

func (*Series[Data, Index]) GetSegment added in v1.0.1

func (s *Series[Data, Index]) GetSegment(t Index) *SeriesSegment[Data, Index]

func (*Series[Data, Index]) Restore

func (s *Series[Data, Index]) Restore(state *SeriesState[Data, Index]) error

func (*Series[Data, Index]) Segments added in v1.0.1

func (s *Series[Data, Index]) Segments() []*SeriesSegment[Data, Index]

func (*Series[Data, Index]) SegmentsString added in v1.0.1

func (s *Series[Data, Index]) SegmentsString() string

For debugging purposes

type SeriesData

type SeriesData[Data any, Index any] interface {
	Get(periodStart, periodEnd Index) ([]Data, error)
	GetEndOpen(periodStart, periodEnd Index) ([]Data, error)
	Merge(data []Data) error
	First(idx Index) (*Data, error)
	Last(idx Index) (*Data, error)
}

func NewArrayData

func NewArrayData[Data any, Index any](
	getIdx func(data *Data) Index,
	idxCmp func(idx1, idx2 Index) int,
	periodStart, periodEnd Index, data []Data,
) (SeriesData[Data, Index], error)

type SeriesDataFactory

type SeriesDataFactory[Data any, Index any] func(
	getIdx func(data *Data) Index,
	idxCmp func(idx1, idx2 Index) int,
	periodStart, periodEnd Index, data []Data,
) (SeriesData[Data, Index], error)

type SeriesSegment added in v1.0.1

type SeriesSegment[Data any, Index any] struct {
	SeriesSegmentFields[Data, Index]
	// contains filtered or unexported fields
}

func NewSeriesSegment added in v1.0.1

func NewSeriesSegment[Data any, Index any](
	storageFactory SeriesDataFactory[Data, Index],
	getIdx func(data *Data) Index,
	idxCmp func(idx1, idx2 Index) int,
	areContinuous func(smaller, bigger Index) bool,
) *SeriesSegment[Data, Index]

func (*SeriesSegment[Data, Index]) CanBeMergedWith added in v1.0.1

func (e *SeriesSegment[Data, Index]) CanBeMergedWith(t Index) bool

func (*SeriesSegment[Data, Index]) ContainsPoint added in v1.0.1

func (e *SeriesSegment[Data, Index]) ContainsPoint(t Index) bool

func (*SeriesSegment[Data, Index]) First added in v1.0.1

func (e *SeriesSegment[Data, Index]) First() (*Data, error)

func (*SeriesSegment[Data, Index]) GetAll added in v1.0.1

func (e *SeriesSegment[Data, Index]) GetAll() ([]Data, error)

func (*SeriesSegment[Data, Index]) GetAllInRange added in v1.0.1

func (e *SeriesSegment[Data, Index]) GetAllInRange(minPeriodStart, maxPeriodEnd Index) (fetchedPeriodStart, fetchedPeriodEnd Index, data []Data, _ error)

func (*SeriesSegment[Data, Index]) Last added in v1.0.1

func (e *SeriesSegment[Data, Index]) Last() (*Data, error)

func (*SeriesSegment[Data, Index]) MergeData added in v1.0.1

func (e *SeriesSegment[Data, Index]) MergeData(data []Data) error

func (*SeriesSegment[Data, Index]) MergePeriod added in v1.0.1

func (e *SeriesSegment[Data, Index]) MergePeriod(periodStart, periodEnd Index, data []Data) error

func (*SeriesSegment[Data, Index]) Restore added in v1.0.1

func (e *SeriesSegment[Data, Index]) Restore(f *SeriesSegmentFields[Data, Index])

type SeriesSegmentFields added in v1.0.1

type SeriesSegmentFields[Data any, Index any] struct {
	PeriodBounds[Index]
	Data  SeriesData[Data, Index]
	Empty bool
}

type SeriesState added in v1.0.1

type SeriesState[Data any, Index any] struct {
	Segments []*SeriesSegmentFields[Data, Index]
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL