-
Notifications
You must be signed in to change notification settings - Fork 690
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
194b608
commit 6594a5e
Showing
7 changed files
with
183 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package processor | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
"sync/atomic" | ||
"time" | ||
|
||
"go.uber.org/zap" | ||
) | ||
|
||
// The format of this time is very picky. Please use the exact format specified by cutOverFmtStr! | ||
const mainnetCutOverTimeStr = "" | ||
const testnetCutOverTimeStr = "" | ||
const devnetCutOverTimeStr = "" | ||
const cutOverFmtStr = "2006-01-02T15:04:05-0700" | ||
|
||
// batchCutoverCompleteFlag indicates if the cutover time has passed, meaning we should publish observation batches. | ||
var batchCutoverCompleteFlag atomic.Bool | ||
|
||
// batchCutoverComplete returns true if the cutover time has passed, meaning we should publish observation batches. | ||
func batchCutoverComplete() bool { | ||
return batchCutoverCompleteFlag.Load() | ||
} | ||
|
||
// evaluateCutOver determines if the cutover time has passed yet and sets the global flag accordingly. If the time has | ||
// not yet passed, it creates a go routine to wait for that time and then sets the flag. | ||
func evaluateBatchCutover(logger *zap.Logger, networkID string) error { | ||
cutOverTimeStr := getCutOverTimeStr(networkID) | ||
|
||
sco, delay, err := evaluateBatchCutoverImpl(logger, cutOverTimeStr, time.Now()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
batchCutoverCompleteFlag.Store(sco) | ||
logger.Info("evaluated cutover flag", zap.Bool("cutOverFlag", batchCutoverComplete()), zap.String("cutOverTime", cutOverTimeStr), zap.String("component", "batchco")) | ||
|
||
if delay != time.Duration(0) { | ||
// Wait for the cut over time and then update the flag. | ||
go func() { | ||
time.Sleep(delay) | ||
logger.Info("time to cut over to batch publishing", zap.String("cutOverTime", cutOverTimeStr), zap.String("component", "batchco")) | ||
batchCutoverCompleteFlag.Store(true) | ||
}() | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// evaluateBatchCutoverImpl performs the actual cut over check. It is a separate function for testing purposes. | ||
func evaluateBatchCutoverImpl(logger *zap.Logger, cutOverTimeStr string, now time.Time) (bool, time.Duration, error) { | ||
if cutOverTimeStr == "" { | ||
return false, 0, nil | ||
} | ||
|
||
cutOverTime, err := time.Parse(cutOverFmtStr, cutOverTimeStr) | ||
if err != nil { | ||
return false, 0, fmt.Errorf(`failed to parse cut over time: %w`, err) | ||
} | ||
|
||
if cutOverTime.Before(now) { | ||
logger.Info("cut over time has passed, should publish observation batches", zap.String("cutOverTime", cutOverTime.Format(cutOverFmtStr)), zap.String("now", now.Format(cutOverFmtStr)), zap.String("component", "batchco")) | ||
return true, 0, nil | ||
} | ||
|
||
// If we get here, we need to wait for the cutover and then switch the global flag. | ||
delay := cutOverTime.Sub(now) | ||
logger.Info("still waiting for cut over time", | ||
zap.Stringer("cutOverTime", cutOverTime), | ||
zap.String("now", now.Format(cutOverFmtStr)), | ||
zap.Stringer("delay", delay), | ||
zap.String("component", "batchco")) | ||
|
||
return false, delay, nil | ||
} | ||
|
||
// getCutOverTimeStr returns the cut over time string based on the network ID passed in. | ||
func getCutOverTimeStr(networkID string) string { //nolint:unparam | ||
if strings.Contains(networkID, "/mainnet/") { | ||
return mainnetCutOverTimeStr | ||
} | ||
if strings.Contains(networkID, "/testnet/") { | ||
return testnetCutOverTimeStr | ||
} | ||
return devnetCutOverTimeStr | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package processor | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"go.uber.org/zap" | ||
) | ||
|
||
func TestVerifyCutOverTime(t *testing.T) { | ||
if mainnetCutOverTimeStr != "" { | ||
_, err := time.Parse(cutOverFmtStr, mainnetCutOverTimeStr) | ||
require.NoError(t, err) | ||
} | ||
if testnetCutOverTimeStr != "" { | ||
_, err := time.Parse(cutOverFmtStr, testnetCutOverTimeStr) | ||
require.NoError(t, err) | ||
} | ||
if devnetCutOverTimeStr != "" { | ||
_, err := time.Parse(cutOverFmtStr, devnetCutOverTimeStr) | ||
require.NoError(t, err) | ||
} | ||
} | ||
|
||
func TestGetCutOverTimeStr(t *testing.T) { | ||
assert.Equal(t, mainnetCutOverTimeStr, getCutOverTimeStr("blah/blah/mainnet/blah")) | ||
assert.Equal(t, testnetCutOverTimeStr, getCutOverTimeStr("blah/blah/testnet/blah")) | ||
assert.Equal(t, devnetCutOverTimeStr, getCutOverTimeStr("blah/blah/devnet/blah")) | ||
} | ||
|
||
func TestCutOverDisabled(t *testing.T) { | ||
logger := zap.NewNop() | ||
|
||
cutOverTimeStr := "" | ||
now, err := time.Parse(cutOverFmtStr, "2023-10-06T18:19:00-0000") | ||
require.NoError(t, err) | ||
|
||
cuttingOver, delay, err := evaluateBatchCutoverImpl(logger, cutOverTimeStr, now) | ||
require.NoError(t, err) | ||
assert.False(t, cuttingOver) | ||
assert.Equal(t, time.Duration(0), delay) | ||
} | ||
|
||
func TestCutOverInvalidTime(t *testing.T) { | ||
logger := zap.NewNop() | ||
|
||
cutOverTimeStr := "Hello World" | ||
now, err := time.Parse(cutOverFmtStr, "2023-10-06T18:19:00-0000") | ||
require.NoError(t, err) | ||
|
||
_, _, err = evaluateBatchCutoverImpl(logger, cutOverTimeStr, now) | ||
require.EqualError(t, err, `failed to parse cut over time: parsing time "Hello World" as "2006-01-02T15:04:05-0700": cannot parse "Hello World" as "2006"`) | ||
} | ||
|
||
func TestCutOverAlreadyHappened(t *testing.T) { | ||
logger := zap.NewNop() | ||
|
||
cutOverTimeStr := "2023-10-06T18:18:00-0000" | ||
now, err := time.Parse(cutOverFmtStr, "2023-10-06T18:19:00-0000") | ||
require.NoError(t, err) | ||
|
||
cuttingOver, delay, err := evaluateBatchCutoverImpl(logger, cutOverTimeStr, now) | ||
require.NoError(t, err) | ||
assert.True(t, cuttingOver) | ||
assert.Equal(t, time.Duration(0), delay) | ||
} | ||
|
||
func TestCutOverDelayRequired(t *testing.T) { | ||
logger := zap.NewNop() | ||
|
||
cutOverTimeStr := "2023-10-06T18:18:00-0000" | ||
now, err := time.Parse(cutOverFmtStr, "2023-10-06T17:18:00-0000") | ||
require.NoError(t, err) | ||
|
||
cuttingOver, delay, err := evaluateBatchCutoverImpl(logger, cutOverTimeStr, now) | ||
require.NoError(t, err) | ||
assert.False(t, cuttingOver) | ||
assert.Equal(t, time.Duration(60*time.Minute), delay) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters