code.vegaprotocol.io/vega@v0.79.0/core/datasource/common/time.go (about)

     1  // Copyright (C) 2023 Gobalsky Labs Limited
     2  //
     3  // This program is free software: you can redistribute it and/or modify
     4  // it under the terms of the GNU Affero General Public License as
     5  // published by the Free Software Foundation, either version 3 of the
     6  // License, or (at your option) any later version.
     7  //
     8  // This program is distributed in the hope that it will be useful,
     9  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    10  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11  // GNU Affero General Public License for more details.
    12  //
    13  // You should have received a copy of the GNU Affero General Public License
    14  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15  
    16  //lint:file-ignore ST1003 Ignore underscores in names, this is straigh copied from the proto package to ease introducing the domain types
    17  
    18  package common
    19  
    20  import (
    21  	"errors"
    22  	"fmt"
    23  	"strings"
    24  	"time"
    25  
    26  	"code.vegaprotocol.io/vega/libs/ptr"
    27  	datapb "code.vegaprotocol.io/vega/protos/vega/data/v1"
    28  )
    29  
    30  type InternalTimeTrigger struct {
    31  	// This is optional to reflect the proto, but it will always be set by the governance
    32  	Initial     *time.Time
    33  	Every       int64
    34  	nextTrigger *time.Time
    35  }
    36  
    37  func (i InternalTimeTrigger) String() string {
    38  	return fmt.Sprintf(
    39  		"initial(%v) every(%d) nextTrigger(%v)",
    40  		i.Initial,
    41  		i.Every,
    42  		i.nextTrigger,
    43  	)
    44  }
    45  
    46  func (i InternalTimeTrigger) IntoProto() *datapb.InternalTimeTrigger {
    47  	var initial *int64
    48  	if i.Initial != nil {
    49  		initial = ptr.From(i.Initial.Unix())
    50  	}
    51  
    52  	return &datapb.InternalTimeTrigger{
    53  		Initial: initial,
    54  		Every:   i.Every,
    55  	}
    56  }
    57  
    58  func (i InternalTimeTrigger) DeepClone() *InternalTimeTrigger {
    59  	var initial *time.Time
    60  	if i.Initial != nil {
    61  		initial = *ptr.From(i.Initial)
    62  	}
    63  
    64  	var nextTrigger *time.Time
    65  	if i.nextTrigger != nil {
    66  		nextTrigger = *ptr.From(i.nextTrigger)
    67  	}
    68  
    69  	return &InternalTimeTrigger{
    70  		Initial:     initial,
    71  		Every:       i.Every,
    72  		nextTrigger: nextTrigger,
    73  	}
    74  }
    75  
    76  func (i InternalTimeTrigger) IsTriggered(timeNow time.Time) bool {
    77  	if i.nextTrigger == nil {
    78  		return false
    79  	}
    80  
    81  	triggered := false
    82  	for i.nextTrigger.Before(timeNow) {
    83  		triggered = true
    84  		*i.nextTrigger = i.nextTrigger.Add(time.Duration(i.Every) * time.Second)
    85  	}
    86  
    87  	return triggered
    88  }
    89  
    90  func (i *InternalTimeTrigger) SetNextTrigger(timeNow time.Time) {
    91  	if i.Initial == nil {
    92  		// Set panic
    93  		panic("initial time value is missing")
    94  	}
    95  
    96  	i.nextTrigger = ptr.From(*i.Initial)
    97  
    98  	// If initial > timeNow, we never been triggered
    99  	// so we set the next trigger to `initial`
   100  	if i.Initial.After(timeNow) {
   101  		return
   102  	}
   103  
   104  	// If `initial` is in the past, we have been triggered already
   105  	// then -> find when the next trigger is
   106  	for i.nextTrigger.Before(timeNow) {
   107  		*i.nextTrigger = i.nextTrigger.Add(time.Duration(i.Every) * time.Second)
   108  	}
   109  }
   110  
   111  func (i *InternalTimeTrigger) SetInitial(initial, timeNow time.Time) {
   112  	if i.Initial != nil {
   113  		// this is incorrect, we should only overwrite time
   114  		// when not submitted by the user
   115  		panic("invalid initial time override")
   116  	}
   117  
   118  	i.Initial = ptr.From(initial)
   119  }
   120  
   121  func InternalTimeTriggerFromProto(
   122  	protoTrigger *datapb.InternalTimeTrigger,
   123  ) *InternalTimeTrigger {
   124  	var initial *time.Time
   125  	if protoTrigger.Initial != nil {
   126  		initial = ptr.From(time.Unix(*protoTrigger.Initial, 0))
   127  	}
   128  
   129  	tt := &InternalTimeTrigger{
   130  		Initial: initial,
   131  		Every:   protoTrigger.Every,
   132  	}
   133  	return tt
   134  }
   135  
   136  type InternalTimeTriggers [1]*InternalTimeTrigger
   137  
   138  func (i InternalTimeTriggers) Empty() error {
   139  	if len(i) <= 0 || i[0] == nil {
   140  		return errors.New("no time trigger is set")
   141  	}
   142  
   143  	return nil
   144  }
   145  
   146  func (i InternalTimeTriggers) String() string {
   147  	if len(i) != 1 {
   148  		return "[]"
   149  	}
   150  
   151  	strs := make([]string, 0, len(i))
   152  	for _, f := range i {
   153  		// We handle length of 1 for the moment, but later will be extended.
   154  		if f == nil {
   155  			strs = append(strs, "nil")
   156  			continue
   157  		}
   158  		strs = append(strs, f.String())
   159  	}
   160  	return "[" + strings.Join(strs, ", ") + "]"
   161  }
   162  
   163  func (i InternalTimeTriggers) IntoProto() []*datapb.InternalTimeTrigger {
   164  	protoTriggers := [1]*datapb.InternalTimeTrigger{}
   165  	if len(i) == 1 {
   166  		if len(i) == 1 && i[0] != nil {
   167  			protoTriggers[0] = i[0].IntoProto()
   168  		}
   169  	}
   170  
   171  	return protoTriggers[:]
   172  }
   173  
   174  func InternalTimeTriggersFromProto(protoTriggers []*datapb.InternalTimeTrigger) InternalTimeTriggers {
   175  	ts := InternalTimeTriggers{}
   176  	for i, protoTrigger := range protoTriggers {
   177  		// Handle length of 1 for now
   178  		if i == 0 {
   179  			ts[0] = InternalTimeTriggerFromProto(protoTrigger)
   180  		}
   181  	}
   182  
   183  	return ts
   184  }
   185  
   186  func (i InternalTimeTriggers) DeepClone() InternalTimeTriggers {
   187  	clonedTriggers := InternalTimeTriggers{}
   188  	if len(i) == 1 && i[0] != nil {
   189  		clonedTriggers[0] = i[0].DeepClone()
   190  	}
   191  
   192  	return clonedTriggers
   193  }
   194  
   195  func (i InternalTimeTriggers) IsTriggered(now time.Time) bool {
   196  	for _, v := range i {
   197  		if v.IsTriggered(now) {
   198  			return true
   199  		}
   200  	}
   201  
   202  	return false
   203  }