Moved utils.go file to internals folder

This commit is contained in:
Kelvin Mwinuka
2024-03-26 14:00:18 +08:00
parent e70d1016e9
commit 7fac4143f5
21 changed files with 2006 additions and 1996 deletions

View File

@@ -61,7 +61,7 @@ func main() {
// Default BindAddr if it's not specified
if config.BindAddr == "" {
if addr, err := utils.GetIPAddress(); err != nil {
if addr, err := internal.GetIPAddress(); err != nil {
log.Fatal(err)
} else {
config.BindAddr = addr

File diff suppressed because it is too large Load Diff

View File

@@ -99,7 +99,7 @@ The options are 'always' for syncing on each command, 'everysec' to sync every s
flag.Func("max-memory", `Upper memory limit before triggering eviction.
Supported units (kb, mb, gb, tb, pb). When 0 is passed, there will be no memory limit.
There is no limit by default.`, func(memory string) error {
b, err := utils.ParseMemory(memory)
b, err := ParseMemory(memory)
if err != nil {
return err
}

View File

@@ -112,7 +112,7 @@ func (delegate *Delegate) NotifyMsg(msgBytes []byte) {
context.WithValue(context.Background(), utils.ContextServerID("ServerID"), string(msg.ServerID)),
utils.ContextConnID("ConnectionID"), msg.ConnId)
cmd, err := utils.Decode(msg.Content)
cmd, err := internal.Decode(msg.Content)
if err != nil {
log.Println(err)
return

View File

@@ -90,7 +90,7 @@ func (m *MemberList) MemberListInit(ctx context.Context) {
}
if m.options.Config.JoinAddr != "" {
backoffPolicy := utils.RetryBackoff(retry.NewFibonacci(1*time.Second), 5, 200*time.Millisecond, 0, 0)
backoffPolicy := internal.RetryBackoff(retry.NewFibonacci(1*time.Second), 5, 200*time.Millisecond, 0, 0)
err = retry.Do(ctx, backoffPolicy, func(ctx context.Context) error {
_, err = list.Join([]string{m.options.Config.JoinAddr})

View File

@@ -52,7 +52,7 @@ func (s *Snapshot) Persist(sink raft.SnapshotSink) error {
}
snapshotObject := utils.SnapshotObject{
State: utils.FilterExpiredKeys(s.options.data),
State: internal.FilterExpiredKeys(s.options.data),
LatestSnapshotMilliseconds: int64(msec),
}

View File

@@ -92,7 +92,7 @@ func (fsm *FSM) Apply(log *raft.Log) interface{} {
handler := command.HandlerFunc
subCommand, ok := utils.GetSubCommand(command, request.CMD).(utils.SubCommand)
subCommand, ok := internal.GetSubCommand(command, request.CMD).(utils.SubCommand)
if ok {
handler = subCommand.HandlerFunc
}
@@ -146,7 +146,7 @@ func (fsm *FSM) Restore(snapshot io.ReadCloser) error {
// Set state
ctx := context.Background()
for k, v := range utils.FilterExpiredKeys(data.State) {
for k, v := range internal.FilterExpiredKeys(data.State) {
if _, err = fsm.options.EchoVault.CreateKeyAndLock(ctx, k); err != nil {
log.Fatal(err)
}

View File

@@ -19,6 +19,7 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"io"
"io/fs"
@@ -205,7 +206,7 @@ func (engine *Engine) TakeSnapshot() error {
// Get current state
snapshotObject := utils.SnapshotObject{
State: utils.FilterExpiredKeys(engine.getStateFunc()),
State: internal.FilterExpiredKeys(engine.getStateFunc()),
LatestSnapshotMilliseconds: engine.getLatestSnapshotTimeFunc(),
}
out, err := json.Marshal(snapshotObject)
@@ -341,7 +342,7 @@ func (engine *Engine) Restore() error {
engine.setLatestSnapshotTimeFunc(snapshotObject.LatestSnapshotMilliseconds)
for key, data := range utils.FilterExpiredKeys(snapshotObject.State) {
for key, data := range internal.FilterExpiredKeys(snapshotObject.State) {
engine.setKeyDataFunc(key, data)
}

View File

@@ -12,13 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package utils
package internal
import (
"bufio"
"bytes"
"errors"
"fmt"
"github.com/echovault/echovault/pkg/utils"
"io"
"log"
"math/big"
@@ -125,7 +126,7 @@ func GetIPAddress() (string, error) {
return localAddr, nil
}
func GetSubCommand(command Command, cmd []string) interface{} {
func GetSubCommand(command utils.Command, cmd []string) interface{} {
if len(command.SubCommands) == 0 || len(cmd) < 2 {
return nil
}
@@ -137,8 +138,8 @@ func GetSubCommand(command Command, cmd []string) interface{} {
return nil
}
func IsWriteCommand(command Command, subCommand SubCommand) bool {
return slices.Contains(append(command.Categories, subCommand.Categories...), WriteCategory)
func IsWriteCommand(command utils.Command, subCommand utils.SubCommand) bool {
return slices.Contains(append(command.Categories, subCommand.Categories...), utils.WriteCategory)
}
func AbsInt(n int) int {
@@ -201,7 +202,7 @@ func IsMaxMemoryExceeded(maxMemory uint64) bool {
}
// FilterExpiredKeys filters out keys that are already expired, so they are not persisted.
func FilterExpiredKeys(state map[string]KeyData) map[string]KeyData {
func FilterExpiredKeys(state map[string]utils.KeyData) map[string]utils.KeyData {
var keysToDelete []string
for k, v := range state {
// Skip keys with no expiry time.

View File

@@ -296,7 +296,7 @@ func (server *EchoVault) handleConnection(ctx context.Context, conn net.Conn) {
fmt.Sprintf("%s-%d", ctx.Value(utils.ContextServerID("ServerID")), cid))
for {
message, err := utils.ReadMessage(r)
message, err := internal.ReadMessage(r)
if err != nil && errors.Is(err, io.EOF) {
// Connection closed

View File

@@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"log"
"math/rand"
@@ -127,7 +128,7 @@ func (server *EchoVault) KeyExists(ctx context.Context, key string) bool {
// CreateKeyAndLock creates a new key lock and immediately locks it if the key does not exist.
// If the key exists, the existing key is locked.
func (server *EchoVault) CreateKeyAndLock(ctx context.Context, key string) (bool, error) {
if utils.IsMaxMemoryExceeded(server.config.MaxMemory) && server.config.EvictionPolicy == utils.NoEviction {
if internal.IsMaxMemoryExceeded(server.config.MaxMemory) && server.config.EvictionPolicy == utils.NoEviction {
return false, errors.New("max memory reached, key not created")
}
@@ -165,7 +166,7 @@ func (server *EchoVault) GetValue(ctx context.Context, key string) interface{} {
// This count triggers a snapshot when the threshold is reached.
// The key must be locked prior to calling this function.
func (server *EchoVault) SetValue(ctx context.Context, key string, value interface{}) error {
if utils.IsMaxMemoryExceeded(server.config.MaxMemory) && server.config.EvictionPolicy == utils.NoEviction {
if internal.IsMaxMemoryExceeded(server.config.MaxMemory) && server.config.EvictionPolicy == utils.NoEviction {
return errors.New("max memory reached, key value not set")
}

View File

@@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"net"
"strings"
@@ -45,7 +46,7 @@ func (server *EchoVault) getCommand(cmd string) (utils.Command, error) {
}
func (server *EchoVault) handleCommand(ctx context.Context, message []byte, conn *net.Conn, replay bool) ([]byte, error) {
cmd, err := utils.Decode(message)
cmd, err := internal.Decode(message)
if err != nil {
return nil, err
}
@@ -58,7 +59,7 @@ func (server *EchoVault) handleCommand(ctx context.Context, message []byte, conn
synchronize := command.Sync
handler := command.HandlerFunc
subCommand, ok := utils.GetSubCommand(command, cmd).(utils.SubCommand)
subCommand, ok := internal.GetSubCommand(command, cmd).(utils.SubCommand)
if ok {
synchronize = subCommand.Sync
handler = subCommand.HandlerFunc
@@ -74,7 +75,7 @@ func (server *EchoVault) handleCommand(ctx context.Context, message []byte, conn
}
// If the command is a write command, wait for state copy to finish.
if utils.IsWriteCommand(command, subCommand) {
if internal.IsWriteCommand(command, subCommand) {
for {
if !server.stateCopyInProgress.Load() {
server.stateMutationInProgress.Store(true)
@@ -89,7 +90,7 @@ func (server *EchoVault) handleCommand(ctx context.Context, message []byte, conn
return nil, err
}
if utils.IsWriteCommand(command, subCommand) && !replay {
if internal.IsWriteCommand(command, subCommand) && !replay {
go server.aofEngine.QueueCommand(message)
}

View File

@@ -19,6 +19,7 @@ import (
"errors"
"flag"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"log"
"net"
@@ -99,7 +100,7 @@ func handleSet(ctx context.Context, cmd []string, server utils.EchoVault, _ *net
}
defer server.KeyUnlock(ctx, key)
if err = server.SetValue(ctx, key, utils.AdaptType(value)); err != nil {
if err = server.SetValue(ctx, key, internal.AdaptType(value)); err != nil {
return nil, err
}
@@ -135,7 +136,7 @@ func handleMSet(ctx context.Context, cmd []string, server utils.EchoVault, _ *ne
for i, key := range cmd[1:] {
if i%2 == 0 {
entries[key] = KeyObject{
value: utils.AdaptType(cmd[1:][i+1]),
value: internal.AdaptType(cmd[1:][i+1]),
locked: false,
}
}

View File

@@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"math/rand"
"net"
@@ -40,7 +41,7 @@ func handleHSET(ctx context.Context, cmd []string, server utils.EchoVault, _ *ne
}
for i := 2; i <= len(cmd)-2; i += 2 {
entries[cmd[i]] = utils.AdaptType(cmd[i+1])
entries[cmd[i]] = internal.AdaptType(cmd[i+1])
}
if !server.KeyExists(ctx, key) {
@@ -306,7 +307,7 @@ func handleHRANDFIELD(ctx context.Context, cmd []string, server utils.EchoVault,
// Pluck fields and return them
var pluckedFields []string
var n int
for i := 0; i < utils.AbsInt(count); i++ {
for i := 0; i < internal.AbsInt(count); i++ {
n = rand.Intn(len(fields))
pluckedFields = append(pluckedFields, fields[n])
// If count is positive, remove the current field from list of fields

View File

@@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"math"
"net"
@@ -57,7 +58,7 @@ func handleLIndex(ctx context.Context, cmd []string, server utils.EchoVault, con
}
key := keys[0]
index, ok := utils.AdaptType(cmd[2]).(int)
index, ok := internal.AdaptType(cmd[2]).(int)
if !ok {
return nil, errors.New("index must be an integer")
@@ -91,8 +92,8 @@ func handleLRange(ctx context.Context, cmd []string, server utils.EchoVault, con
}
key := keys[0]
start, startOk := utils.AdaptType(cmd[2]).(int)
end, endOk := utils.AdaptType(cmd[3]).(int)
start, startOk := internal.AdaptType(cmd[2]).(int)
end, endOk := internal.AdaptType(cmd[3]).(int)
if !startOk || !endOk {
return nil, errors.New("start and end indices must be integers")
@@ -171,7 +172,7 @@ func handleLSet(ctx context.Context, cmd []string, server utils.EchoVault, conn
key := keys[0]
index, ok := utils.AdaptType(cmd[2]).(int)
index, ok := internal.AdaptType(cmd[2]).(int)
if !ok {
return nil, errors.New("index must be an integer")
}
@@ -194,7 +195,7 @@ func handleLSet(ctx context.Context, cmd []string, server utils.EchoVault, conn
return nil, errors.New("index must be within list range")
}
list[index] = utils.AdaptType(cmd[3])
list[index] = internal.AdaptType(cmd[3])
if err = server.SetValue(ctx, key, list); err != nil {
return nil, err
}
@@ -209,8 +210,8 @@ func handleLTrim(ctx context.Context, cmd []string, server utils.EchoVault, conn
}
key := keys[0]
start, startOk := utils.AdaptType(cmd[2]).(int)
end, endOk := utils.AdaptType(cmd[3]).(int)
start, startOk := internal.AdaptType(cmd[2]).(int)
end, endOk := internal.AdaptType(cmd[3]).(int)
if !startOk || !endOk {
return nil, errors.New("start and end indices must be integers")
@@ -260,12 +261,12 @@ func handleLRem(ctx context.Context, cmd []string, server utils.EchoVault, conn
key := keys[0]
value := cmd[3]
count, ok := utils.AdaptType(cmd[2]).(int)
count, ok := internal.AdaptType(cmd[2]).(int)
if !ok {
return nil, errors.New("count must be an integer")
}
absoluteCount := utils.AbsInt(count)
absoluteCount := internal.AbsInt(count)
if !server.KeyExists(ctx, key) {
return nil, errors.New("LREM command on non-list item")
@@ -389,7 +390,7 @@ func handleLPush(ctx context.Context, cmd []string, server utils.EchoVault, conn
var newElems []interface{}
for _, elem := range cmd[2:] {
newElems = append(newElems, utils.AdaptType(elem))
newElems = append(newElems, internal.AdaptType(elem))
}
key := keys[0]
@@ -437,7 +438,7 @@ func handleRPush(ctx context.Context, cmd []string, server utils.EchoVault, conn
var newElems []interface{}
for _, elem := range cmd[2:] {
newElems = append(newElems, utils.AdaptType(elem))
newElems = append(newElems, internal.AdaptType(elem))
}
if !server.KeyExists(ctx, key) {

View File

@@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"net"
"slices"
@@ -300,7 +301,7 @@ func handleSINTERCARD(ctx context.Context, cmd []string, server utils.EchoVault,
return nil, errors.New("provide limit after LIMIT keyword")
}
if l, ok := utils.AdaptType(cmd[limitIdx]).(int); !ok {
if l, ok := internal.AdaptType(cmd[limitIdx]).(int); !ok {
return nil, errors.New("limit must be an integer")
} else {
limit = l
@@ -576,7 +577,7 @@ func handleSPOP(ctx context.Context, cmd []string, server utils.EchoVault, conn
count := 1
if len(cmd) == 3 {
c, ok := utils.AdaptType(cmd[2]).(int)
c, ok := internal.AdaptType(cmd[2]).(int)
if !ok {
return nil, errors.New("count must be an integer")
}
@@ -620,7 +621,7 @@ func handleSRANDMEMBER(ctx context.Context, cmd []string, server utils.EchoVault
count := 1
if len(cmd) == 3 {
c, ok := utils.AdaptType(cmd[2]).(int)
c, ok := internal.AdaptType(cmd[2]).(int)
if !ok {
return nil, errors.New("count must be an integer")
}

View File

@@ -15,7 +15,7 @@
package set
import (
"github.com/echovault/echovault/pkg/utils"
"github.com/echovault/echovault/internal"
"math/rand"
"slices"
)
@@ -69,7 +69,7 @@ func (set *Set) GetRandom(count int) []string {
return []string{}
}
if utils.AbsInt(count) >= set.Cardinality() {
if internal.AbsInt(count) >= set.Cardinality() {
return keys
}
@@ -79,13 +79,13 @@ func (set *Set) GetRandom(count int) []string {
if count < 0 {
// If count is negative, allow repeat elements
for i := 0; i < utils.AbsInt(count); i++ {
for i := 0; i < internal.AbsInt(count); i++ {
n = rand.Intn(len(keys))
res = append(res, keys[n])
}
} else {
// Count is positive, do not allow repeat elements
for i := 0; i < utils.AbsInt(count); {
for i := 0; i < internal.AbsInt(count); {
n = rand.Intn(len(keys))
if !slices.Contains(res, keys[n]) {
res = append(res, keys[n])

View File

@@ -19,6 +19,7 @@ import (
"context"
"errors"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"math"
"net"
@@ -46,7 +47,7 @@ func handleZADD(ctx context.Context, cmd []string, server utils.EchoVault, conn
if membersStartIndex != 0 {
break
}
switch utils.AdaptType(cmd[i]).(type) {
switch internal.AdaptType(cmd[i]).(type) {
case string:
if slices.Contains([]string{"-inf", "+inf"}, strings.ToLower(cmd[i])) {
membersStartIndex = i
@@ -68,7 +69,7 @@ func handleZADD(ctx context.Context, cmd []string, server utils.EchoVault, conn
if i%2 != 0 {
continue
}
score := utils.AdaptType(cmd[membersStartIndex:][i])
score := internal.AdaptType(cmd[membersStartIndex:][i])
switch score.(type) {
default:
return nil, errors.New("invalid score in score/member list")
@@ -211,7 +212,7 @@ func handleZCOUNT(ctx context.Context, cmd []string, server utils.EchoVault, con
key := keys[0]
minimum := Score(math.Inf(-1))
switch utils.AdaptType(cmd[2]).(type) {
switch internal.AdaptType(cmd[2]).(type) {
default:
return nil, errors.New("min constraint must be a double")
case string:
@@ -221,15 +222,15 @@ func handleZCOUNT(ctx context.Context, cmd []string, server utils.EchoVault, con
return nil, errors.New("min constraint must be a double")
}
case float64:
s, _ := utils.AdaptType(cmd[2]).(float64)
s, _ := internal.AdaptType(cmd[2]).(float64)
minimum = Score(s)
case int:
s, _ := utils.AdaptType(cmd[2]).(int)
s, _ := internal.AdaptType(cmd[2]).(int)
minimum = Score(s)
}
maximum := Score(math.Inf(1))
switch utils.AdaptType(cmd[3]).(type) {
switch internal.AdaptType(cmd[3]).(type) {
default:
return nil, errors.New("max constraint must be a double")
case string:
@@ -239,10 +240,10 @@ func handleZCOUNT(ctx context.Context, cmd []string, server utils.EchoVault, con
return nil, errors.New("max constraint must be a double")
}
case float64:
s, _ := utils.AdaptType(cmd[3]).(float64)
s, _ := internal.AdaptType(cmd[3]).(float64)
maximum = Score(s)
case int:
s, _ := utils.AdaptType(cmd[3]).(int)
s, _ := internal.AdaptType(cmd[3]).(int)
maximum = Score(s)
}
@@ -464,7 +465,7 @@ func handleZINCRBY(ctx context.Context, cmd []string, server utils.EchoVault, co
member := Value(cmd[3])
var increment Score
switch utils.AdaptType(cmd[2]).(type) {
switch internal.AdaptType(cmd[2]).(type) {
default:
return nil, errors.New("increment must be a double")
case string:
@@ -476,10 +477,10 @@ func handleZINCRBY(ctx context.Context, cmd []string, server utils.EchoVault, co
return nil, errors.New("increment must be a double")
}
case float64:
s, _ := utils.AdaptType(cmd[2]).(float64)
s, _ := internal.AdaptType(cmd[2]).(float64)
increment = Score(s)
case int:
s, _ := utils.AdaptType(cmd[2]).(int)
s, _ := internal.AdaptType(cmd[2]).(int)
increment = Score(s)
}

View File

@@ -17,7 +17,7 @@ package sorted_set
import (
"cmp"
"errors"
"github.com/echovault/echovault/pkg/utils"
"github.com/echovault/echovault/internal"
"math"
"math/rand"
"slices"
@@ -72,7 +72,7 @@ func (set *SortedSet) GetRandom(count int) []MemberParam {
members := set.GetAll()
if utils.AbsInt(count) >= len(members) {
if internal.AbsInt(count) >= len(members) {
return members
}
@@ -80,13 +80,13 @@ func (set *SortedSet) GetRandom(count int) []MemberParam {
if count < 0 {
// If count is negative, allow repeat numbers
for i := 0; i < utils.AbsInt(count); i++ {
for i := 0; i < internal.AbsInt(count); i++ {
n = rand.Intn(len(members))
res = append(res, members[n])
}
} else {
// If count is positive only allow unique values
for i := 0; i < utils.AbsInt(count); {
for i := 0; i < internal.AbsInt(count); {
n = rand.Intn(len(members))
if !slices.ContainsFunc(res, func(m MemberParam) bool {
return m.value == members[n].value

View File

@@ -18,6 +18,7 @@ import (
"context"
"errors"
"fmt"
"github.com/echovault/echovault/internal"
"github.com/echovault/echovault/pkg/utils"
"net"
)
@@ -30,7 +31,7 @@ func handleSetRange(ctx context.Context, cmd []string, server utils.EchoVault, c
key := keys[0]
offset, ok := utils.AdaptType(cmd[2]).(int)
offset, ok := internal.AdaptType(cmd[2]).(int)
if !ok {
return nil, errors.New("offset must be an integer")
}
@@ -131,8 +132,8 @@ func handleSubStr(ctx context.Context, cmd []string, server utils.EchoVault, con
key := keys[0]
start, startOk := utils.AdaptType(cmd[2]).(int)
end, endOk := utils.AdaptType(cmd[3]).(int)
start, startOk := internal.AdaptType(cmd[2]).(int)
end, endOk := internal.AdaptType(cmd[3]).(int)
reversed := false
if !startOk || !endOk {
@@ -154,10 +155,10 @@ func handleSubStr(ctx context.Context, cmd []string, server utils.EchoVault, con
}
if start < 0 {
start = len(value) - utils.AbsInt(start)
start = len(value) - internal.AbsInt(start)
}
if end < 0 {
end = len(value) - utils.AbsInt(end)
end = len(value) - internal.AbsInt(end)
}
if end >= 0 && end >= start {

View File

@@ -138,7 +138,7 @@ func Test_HandleSetRange(t *testing.T) {
if _, err := mockServer.CreateKeyAndLock(ctx, test.key); err != nil {
t.Error(err)
}
if err := mockServer.SetValue(ctx, test.key, utils.AdaptType(test.presetValue)); err != nil {
if err := mockServer.SetValue(ctx, test.key, internal.AdaptType(test.presetValue)); err != nil {
t.Error(err)
}
mockServer.KeyUnlock(ctx, test.key)