From f49604bcf8904c8e6382ff6238c6bb0f23620b5c Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Tue, 3 Dec 2024 11:39:31 +0530 Subject: [PATCH 01/25] ELiminating redundant checks --- internal/eval/bytearray.go | 2 +- internal/eval/eval_test.go | 4 ++-- internal/eval/store_eval.go | 33 +++++++++----------------- internal/eval/type_string.go | 46 ++++++++++++++++-------------------- internal/object/deep_copy.go | 2 +- internal/object/object.go | 4 ---- 6 files changed, 36 insertions(+), 55 deletions(-) diff --git a/internal/eval/bytearray.go b/internal/eval/bytearray.go index 45900aa21..dd0d1813d 100644 --- a/internal/eval/bytearray.go +++ b/internal/eval/bytearray.go @@ -36,7 +36,7 @@ func NewByteArrayFromObj(obj *object.Obj) (*ByteArray, error) { } func getValueAsByteSlice(obj *object.Obj) ([]byte, error) { - oType := object.ExtractType(obj) + oType := obj.Type switch oType { case object.ObjTypeInt: return []byte(strconv.FormatInt(obj.Value.(int64), 10)), nil diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index 61ae149fe..1ecab654c 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -6719,7 +6719,7 @@ func testEvalAPPEND(t *testing.T, store *dstore.Store) { migratedOutput: EvalResponse{Result: 3, Error: nil}, validator: func(output []byte) { obj := store.Get("key") - oType := object.ExtractType(obj) + oType := obj.Type if oType != object.ObjTypeInt { t.Errorf("unexpected encoding") } @@ -6774,7 +6774,7 @@ func testEvalAPPEND(t *testing.T, store *dstore.Store) { migratedOutput: EvalResponse{Result: 2, Error: nil}, validator: func(output []byte) { obj := store.Get("key") - oType := object.ExtractType(obj) + oType := obj.Type if oType != object.ObjTypeString { t.Errorf("unexpected encoding") } diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 37b694f5e..3566a76ff 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -338,7 +338,7 @@ func evalGET(args []string, store *dstore.Store) *EvalResponse { } // Decode and return the value based on its encoding - switch oType := object.ExtractType(obj); oType { + switch oType := obj.Type; oType { case object.ObjTypeInt: // Value is stored as an int64, so use type assertion if IsInt64(obj.Value) { @@ -642,7 +642,7 @@ func evalGETRANGE(args []string, store *dstore.Store) *EvalResponse { } var str string - switch oType := object.ExtractType(obj); oType { + switch oType := obj.Type; oType { case object.ObjTypeString: if val, ok := obj.Value.(string); ok { str = val @@ -1095,18 +1095,7 @@ func evalAPPEND(args []string, store *dstore.Store) *EvalResponse { // Key does not exist, create a new key if obj == nil { - // Deduce type and encoding based on the value if no leading zeros - oType := deduceType(value) - - // Transform the value based on the type and encoding - storedValue, err := storeValueWithType(value, oType) - if err != nil { - return &EvalResponse{ - Result: nil, - Error: err, - } - } - + storedValue, oType := getRawStringOrInt(value) store.Put(key, store.NewObj(storedValue, exDurationMs, oType)) return &EvalResponse{ Result: len(value), @@ -1121,7 +1110,7 @@ func evalAPPEND(args []string, store *dstore.Store) *EvalResponse { Error: diceerrors.ErrWrongTypeOperation, } } - oType := object.ExtractType(obj) + oType := obj.Type // Transform the value based on the current encoding currentValue, err := convertValueToString(obj, oType) @@ -4441,7 +4430,7 @@ func evalGETDEL(args []string, store *dstore.Store) *EvalResponse { objVal := store.GetDel(key) // Decode and return the value based on its encoding - switch oType := object.ExtractType(objVal); oType { + switch oType := objVal.Type; oType { case object.ObjTypeInt: // Value is stored as an int64, so use type assertion if IsInt64(objVal.Value) { @@ -5082,7 +5071,7 @@ func evalSETBIT(args []string, store *dstore.Store) *EvalResponse { object.AssertType(obj.Type, object.ObjTypeString) == nil || object.AssertType(obj.Type, object.ObjTypeInt) == nil { var byteArray *ByteArray - oType := object.ExtractType(obj) + oType := obj.Type switch oType { case object.ObjTypeByteArray: @@ -5180,7 +5169,7 @@ func evalGETBIT(args []string, store *dstore.Store) *EvalResponse { } requiredByteArraySize := offset>>3 + 1 - switch oType := object.ExtractType(obj); oType { + switch oType := obj.Type; oType { case object.ObjTypeSet: return &EvalResponse{ Result: nil, @@ -5429,7 +5418,7 @@ func bitfieldEvalGeneric(args []string, store *dstore.Store, isReadOnly bool) *E var value *ByteArray var err error - switch oType := object.ExtractType(obj); oType { + switch oType := obj.Type; oType { case object.ObjTypeByteArray: value = obj.Value.(*ByteArray) case object.ObjTypeString, object.ObjTypeInt: @@ -6383,7 +6372,7 @@ func evalTYPE(args []string, store *dstore.Store) *EvalResponse { } var typeStr string - switch oType := object.ExtractType(obj); oType { + switch oType := obj.Type; oType { case object.ObjTypeString, object.ObjTypeInt, object.ObjTypeByteArray: typeStr = "string" case object.ObjTypeDequeue: @@ -6430,7 +6419,7 @@ func evalTYPE(args []string, store *dstore.Store) *EvalResponse { // var value []byte -// switch oType, _ := object.ExtractType(obj); oType { +// switch oType, _ := obj.Type; oType { // case object.ObjTypeByteArray: // byteArray := obj.Value.(*ByteArray) // byteArrayObject := *byteArray @@ -6491,7 +6480,7 @@ func evalTYPE(args []string, store *dstore.Store) *EvalResponse { // values[i] = make([]byte, 0) // } else { // // handle the case when it is byte array -// switch oType, _ := object.ExtractType(obj); oType { +// switch oType, _ := obj.Type; oType { // case object.ObjTypeByteArray: // byteArray := obj.Value.(*ByteArray) // byteArrayObject := *byteArray diff --git a/internal/eval/type_string.go b/internal/eval/type_string.go index dc4c716be..f320f5510 100644 --- a/internal/eval/type_string.go +++ b/internal/eval/type_string.go @@ -7,8 +7,22 @@ import ( "github.com/dicedb/dice/internal/object" ) -// Similar to -// tryObjectEncoding function in Redis +type String struct { + Value string + Type uint8 +} + +func NewString(value string) *String { + return &String{ + Value: value, + Type: object.ObjTypeString, + } +} + +func (s *String) Serialize() []byte { + return []byte{} +} + func deduceType(v string) (o uint8) { // Check if the value has leading zero if len(v) > 1 && v[0] == '0' { @@ -21,30 +35,12 @@ func deduceType(v string) (o uint8) { return object.ObjTypeString } -// Function to handle converting the value based on the encoding type -func storeValueWithType(value string, oType uint8) (interface{}, error) { - var returnValue interface{} - - // treat as string if value has leading zero - if len(value) > 1 && value[0] == '0' { - // If so, treat as string - return value, nil +func getRawStringOrInt(value string) (interface{}, uint8) { + intValue, err := strconv.ParseInt(value, 10, 64) + if err != nil { // value is not an integer, hence a string + return value, object.ObjTypeString } - - switch oType { - case object.ObjTypeInt: - intValue, err := strconv.ParseInt(value, 10, 64) - if err != nil { - return nil, diceerrors.ErrWrongTypeOperation - } - returnValue = intValue - case object.ObjTypeString: - returnValue = value - default: - return nil, diceerrors.ErrWrongTypeOperation - } - - return returnValue, nil + return intValue, object.ObjTypeInt // value is an integer } // Function to convert the value to a string for concatenation or manipulation diff --git a/internal/object/deep_copy.go b/internal/object/deep_copy.go index 18a10b73d..0e211be9f 100644 --- a/internal/object/deep_copy.go +++ b/internal/object/deep_copy.go @@ -19,7 +19,7 @@ func (obj *Obj) DeepCopy() *Obj { newObj.Value = copier.DeepCopy() } else { // Handle types that are not DeepCopyable - sourceType := ExtractType(obj) + sourceType := obj.Type switch sourceType { case ObjTypeString: sourceValue := obj.Value.(string) diff --git a/internal/object/object.go b/internal/object/object.go index 63b6b0c30..630230980 100644 --- a/internal/object/object.go +++ b/internal/object/object.go @@ -82,7 +82,3 @@ var ObjTypeSortedSet uint8 = 8 var ObjTypeCountMinSketch uint8 = 9 var ObjTypeBF uint8 = 10 var ObjTypeDequeue uint8 = 11 - -func ExtractType(obj *Obj) (e1 uint8) { - return obj.Type -} From 45fb9864749ea2216c25f7ad7b30d191fd83be64 Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Tue, 3 Dec 2024 11:45:56 +0530 Subject: [PATCH 02/25] Creating a type for ObjectType instead of vanilla uint8 --- internal/eval/bytearray.go | 2 +- internal/eval/eval.go | 2 +- internal/eval/store_eval.go | 6 +++--- internal/eval/type_string.go | 20 ++++++-------------- internal/object/object.go | 30 +++++++++++++++++++----------- internal/object/typeencoding.go | 4 ++-- internal/store/store.go | 2 +- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/internal/eval/bytearray.go b/internal/eval/bytearray.go index dd0d1813d..4bf4f1f0a 100644 --- a/internal/eval/bytearray.go +++ b/internal/eval/bytearray.go @@ -81,7 +81,7 @@ func getByteArrayValueAsByteSlice(obj *object.Obj) ([]byte, error) { } // ByteSliceToObj converts a byte slice to an Obj of the specified type and encoding -func ByteSliceToObj(store *dstore.Store, oldObj *object.Obj, b []byte, objType uint8) (*object.Obj, error) { +func ByteSliceToObj(store *dstore.Store, oldObj *object.Obj, b []byte, objType object.ObjectType) (*object.Obj, error) { switch objType { case object.ObjTypeInt: return ByteSliceToIntObj(store, oldObj, b) diff --git a/internal/eval/eval.go b/internal/eval/eval.go index 7c1173b1f..95f708c96 100644 --- a/internal/eval/eval.go +++ b/internal/eval/eval.go @@ -165,7 +165,7 @@ func evalMSET(args []string, store *dstore.Store) []byte { insertMap := make(map[string]*object.Obj, len(args)/2) for i := 0; i < len(args); i += 2 { key, value := args[i], args[i+1] - oType := deduceType(value) + _, oType := getRawStringOrInt(value) var storedValue interface{} switch oType { case object.ObjTypeInt: diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 3566a76ff..4fe6f04cd 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -201,7 +201,7 @@ func evalSET(args []string, store *dstore.Store) *EvalResponse { var oldVal *interface{} key, value = args[0], args[1] - oType := deduceType(value) + _, oType := getRawStringOrInt(value) for i := 2; i < len(args); i++ { arg := strings.ToUpper(args[i]) @@ -2477,7 +2477,7 @@ func incrByFloatCmd(args []string, incr float64, store *dstore.Store) *EvalRespo if obj == nil { strValue := formatFloat(incr, false) - oType := deduceType(strValue) + _, oType := getRawStringOrInt(strValue) obj = store.NewObj(strValue, -1, oType) store.Put(key, obj) return &EvalResponse{ @@ -2511,7 +2511,7 @@ func incrByFloatCmd(args []string, incr float64, store *dstore.Store) *EvalRespo } strValue := formatFloat(value, true) - oType := deduceType(strValue) + _, oType := getRawStringOrInt(strValue) // Remove the trailing decimal for integer values // to maintain consistency with redis diff --git a/internal/eval/type_string.go b/internal/eval/type_string.go index f320f5510..3553a00f5 100644 --- a/internal/eval/type_string.go +++ b/internal/eval/type_string.go @@ -9,7 +9,7 @@ import ( type String struct { Value string - Type uint8 + Type object.ObjectType } func NewString(value string) *String { @@ -23,28 +23,20 @@ func (s *String) Serialize() []byte { return []byte{} } -func deduceType(v string) (o uint8) { - // Check if the value has leading zero +func getRawStringOrInt(v string) (interface{}, object.ObjectType) { if len(v) > 1 && v[0] == '0' { // If so, treat as string - return object.ObjTypeString + return v, object.ObjTypeString } - if _, err := strconv.ParseInt(v, 10, 64); err == nil { - return object.ObjTypeInt - } - return object.ObjTypeString -} - -func getRawStringOrInt(value string) (interface{}, uint8) { - intValue, err := strconv.ParseInt(value, 10, 64) + intValue, err := strconv.ParseInt(v, 10, 64) if err != nil { // value is not an integer, hence a string - return value, object.ObjTypeString + return v, object.ObjTypeString } return intValue, object.ObjTypeInt // value is an integer } // Function to convert the value to a string for concatenation or manipulation -func convertValueToString(obj *object.Obj, oType uint8) (string, error) { +func convertValueToString(obj *object.Obj, oType object.ObjectType) (string, error) { var currentValueStr string switch oType { diff --git a/internal/object/object.go b/internal/object/object.go index 630230980..24c8527a5 100644 --- a/internal/object/object.go +++ b/internal/object/object.go @@ -25,7 +25,7 @@ package object // objects (e.g., strings, numbers, complex data structures like lists or maps). type Obj struct { // Type holds the type of the object (e.g., string, int, complex structure) - Type uint8 + Type ObjectType // LastAccessedAt stores the last access timestamp of the object. // It helps track when the object was last accessed and may be used for cache eviction or freshness tracking. @@ -72,13 +72,21 @@ type InternalObj struct { ExDuration int64 } -var ObjTypeString uint8 = 0 -var ObjTypeJSON uint8 = 3 -var ObjTypeByteArray uint8 = 4 -var ObjTypeInt uint8 = 5 -var ObjTypeSet uint8 = 6 -var ObjTypeHashMap uint8 = 7 -var ObjTypeSortedSet uint8 = 8 -var ObjTypeCountMinSketch uint8 = 9 -var ObjTypeBF uint8 = 10 -var ObjTypeDequeue uint8 = 11 +// ObjectType represents the type of a DiceDB object +type ObjectType uint8 + +// Define object types as constants +const ( + ObjTypeString ObjectType = iota + _ // skip 1 and 2 to maintain compatibility + _ + ObjTypeJSON + ObjTypeByteArray + ObjTypeInt + ObjTypeSet + ObjTypeHashMap + ObjTypeSortedSet + ObjTypeCountMinSketch + ObjTypeBF + ObjTypeDequeue +) diff --git a/internal/object/typeencoding.go b/internal/object/typeencoding.go index b8f677066..8934fe710 100644 --- a/internal/object/typeencoding.go +++ b/internal/object/typeencoding.go @@ -6,14 +6,14 @@ import ( diceerrors "github.com/dicedb/dice/internal/errors" ) -func AssertTypeWithError(te, t uint8) error { +func AssertTypeWithError(te, t ObjectType) error { if te != t { return errors.New("WRONGTYPE Operation against a key holding the wrong kind of value") } return nil } -func AssertType(_type, expectedType uint8) []byte { +func AssertType(_type, expectedType ObjectType) []byte { if err := AssertTypeWithError(_type, expectedType); err != nil { return diceerrors.NewErrWithMessage(diceerrors.WrongKeyTypeErr) } diff --git a/internal/store/store.go b/internal/store/store.go index 5c1f46297..6bb18aecb 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -84,7 +84,7 @@ func ResetStore(store *Store) *Store { return store } -func (store *Store) NewObj(value interface{}, expDurationMs int64, oType uint8) *object.Obj { +func (store *Store) NewObj(value interface{}, expDurationMs int64, oType object.ObjectType) *object.Obj { obj := &object.Obj{ Value: value, Type: oType, From 6d4a7568a5f43284f9e703f92ee1a595abe789da Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Tue, 3 Dec 2024 11:48:29 +0530 Subject: [PATCH 03/25] Removing the additional check --- internal/eval/eval.go | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/internal/eval/eval.go b/internal/eval/eval.go index 95f708c96..0b28e079d 100644 --- a/internal/eval/eval.go +++ b/internal/eval/eval.go @@ -165,16 +165,7 @@ func evalMSET(args []string, store *dstore.Store) []byte { insertMap := make(map[string]*object.Obj, len(args)/2) for i := 0; i < len(args); i += 2 { key, value := args[i], args[i+1] - _, oType := getRawStringOrInt(value) - var storedValue interface{} - switch oType { - case object.ObjTypeInt: - storedValue, _ = strconv.ParseInt(value, 10, 64) - case object.ObjTypeString: - storedValue = value - default: - return clientio.Encode(fmt.Errorf("ERR unsupported type: %d", oType), false) - } + storedValue, oType := getRawStringOrInt(value) insertMap[key] = store.NewObj(storedValue, exDurationMs, oType) } From 1355e7c3346fbe4b9e2d38492d8b657a11c8e516 Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Tue, 3 Dec 2024 15:27:12 +0530 Subject: [PATCH 04/25] Bloomfilter naming conventions --- internal/eval/bloom_test.go | 6 +-- internal/eval/store_eval.go | 35 +++++++------- internal/eval/{bloom.go => type_bloom.go} | 56 +++++++++++------------ internal/eval/type_string.go | 6 +-- 4 files changed, 51 insertions(+), 52 deletions(-) rename internal/eval/{bloom.go => type_bloom.go} (87%) diff --git a/internal/eval/bloom_test.go b/internal/eval/bloom_test.go index 3d06c3daa..5ef929250 100644 --- a/internal/eval/bloom_test.go +++ b/internal/eval/bloom_test.go @@ -100,19 +100,19 @@ func TestGetOrCreateBloomFilter(t *testing.T) { opts := defaultBloomOpts() // Should create a new filter under the key `key`. - bloom, err := getOrCreateBloomFilter(key, store, opts) + bloom, err := GetOrCreateBloomFilter(key, store, opts) if bloom == nil || err != nil { t.Errorf("nil bloom or non-nil error returned while creating new filter - key: %s, opts: %+v, err: %v", key, opts, err) } // Should get the filter (which was created above) - bloom, err = getOrCreateBloomFilter(key, store, opts) + bloom, err = GetOrCreateBloomFilter(key, store, opts) if bloom == nil || err != nil { t.Errorf("nil bloom or non-nil error returned while fetching existing filter - key: %s, opts: %+v, err: %v", key, opts, err) } // Should get the filter with nil opts - bloom, err = getOrCreateBloomFilter(key, store, nil) + bloom, err = GetOrCreateBloomFilter(key, store, nil) if bloom == nil || err != nil { t.Errorf("nil bloom or non-nil error returned while fetching existing filter - key: %s, opts: %+v, err: %v", key, opts, err) } diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 4fe6f04cd..343a386e4 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -2867,11 +2867,17 @@ func evalBFRESERVE(args []string, store *dstore.Store) *EvalResponse { return makeEvalError(err) } - _, err = CreateBloomFilter(args[0], store, opts) - if err != nil { + key := args[0] + + _, err = GetBloomFilter(key, store) + if err != nil && err != diceerrors.ErrKeyNotFound { // bloom filter does not exist return makeEvalError(err) + } else if err != nil && err == diceerrors.ErrKeyNotFound { // key does not exists + CreateOrReplaceBloomFilter(key, opts, store) + return makeEvalResult(clientio.OK) + } else { // bloom filter already exists + return makeEvalResult(clientio.OK) } - return makeEvalResult(clientio.OK) } // evalBFADD evaluates the BF.ADD command responsible for adding an element to a bloom filter. If the filter does not @@ -2881,12 +2887,12 @@ func evalBFADD(args []string, store *dstore.Store) *EvalResponse { return makeEvalError(diceerrors.ErrWrongArgumentCount("BF.ADD")) } - bloom, err := getOrCreateBloomFilter(args[0], store, nil) + bf, err := GetOrCreateBloomFilter(args[0], store, nil) if err != nil { return makeEvalError(err) } - result, err := bloom.add(args[1]) + result, err := bf.add(args[1]) if err != nil { return makeEvalError(err) } @@ -2901,14 +2907,14 @@ func evalBFEXISTS(args []string, store *dstore.Store) *EvalResponse { return makeEvalError(diceerrors.ErrWrongArgumentCount("BF.EXISTS")) } - bloom, err := GetBloomFilter(args[0], store) - if err != nil { + bf, err := GetBloomFilter(args[0], store) + if err != nil && err != diceerrors.ErrKeyNotFound { return makeEvalError(err) - } - if bloom == nil { + } else if err != nil && err == diceerrors.ErrKeyNotFound { return makeEvalResult(clientio.IntegerZero) } - result, err := bloom.exists(args[1]) + + result, err := bf.exists(args[1]) if err != nil { return makeEvalError(err) } @@ -2922,25 +2928,20 @@ func evalBFINFO(args []string, store *dstore.Store) *EvalResponse { return makeEvalError(diceerrors.ErrWrongArgumentCount("BF.INFO")) } - bloom, err := GetBloomFilter(args[0], store) - + bf, err := GetBloomFilter(args[0], store) if err != nil { return makeEvalError(err) } - if bloom == nil { - return makeEvalError(diceerrors.ErrGeneral("not found")) - } opt := "" if len(args) == 2 { opt = args[1] } - result, err := bloom.info(opt) + result, err := bf.info(opt) if err != nil { return makeEvalError(err) } - return makeEvalResult(result) } diff --git a/internal/eval/bloom.go b/internal/eval/type_bloom.go similarity index 87% rename from internal/eval/bloom.go rename to internal/eval/type_bloom.go index 35b893705..3d7a6072c 100644 --- a/internal/eval/bloom.go +++ b/internal/eval/type_bloom.go @@ -92,7 +92,7 @@ func newBloomOpts(args []string) (*BloomOpts, error) { // newBloomFilter creates and returns a new filter. It is responsible for initializing the // underlying bit array. -func newBloomFilter(opts *BloomOpts) *Bloom { +func NewBloom(opts *BloomOpts) *Bloom { // Calculate bits per element // bpe = -log(errorRate)/ln(2)^2 num := -1 * math.Log(opts.errorRate) @@ -278,25 +278,41 @@ func (opts *BloomOpts) updateIndexes(value string) error { return nil } -// getOrCreateBloomFilter attempts to fetch an existing bloom filter from -// the kv store. If it does not exist, it tries to create one with -// given `opts` and returns it. -func getOrCreateBloomFilter(key string, store *dstore.Store, opts *BloomOpts) (*Bloom, error) { +// CreateOrReplaceBloomFilter creates a new bloom filter with given `opts` +// and stores it in the kv store. If the bloom filter already exists, it +// replaces the existing one. If `opts` is nil, it uses the default options. +func CreateOrReplaceBloomFilter(key string, opts *BloomOpts, store *dstore.Store) *Bloom { + if opts == nil { + opts = defaultBloomOpts() + } + bf := NewBloom(opts) + obj := store.NewObj(bf, -1, object.ObjTypeBF) + store.Put(key, obj) + return bf +} + +// GetOrCreateBloomFilter fetches an existing bloom filter from +// the kv store and returns the datastructure instance of it. +// If it does not exist, it tries to create one with given `opts` and returns it. +// Note: It also stores it in the kv store. +func GetOrCreateBloomFilter(key string, store *dstore.Store, opts *BloomOpts) (*Bloom, error) { bf, err := GetBloomFilter(key, store) - if err != nil { + if err != nil && err != diceerrors.ErrKeyNotFound { return nil, err + } else if err != nil && err == diceerrors.ErrKeyNotFound { + bf = CreateOrReplaceBloomFilter(key, opts, store) } - if bf == nil { - bf, err = CreateBloomFilter(key, store, opts) - } - return bf, err + return bf, nil } -// get the bloom filter +// GetBloomFilter fetches an existing bloom filter from +// the kv store and returns the datastructure instance of it. +// The function also returns diceerrors.ErrKeyNotFound if the key does not exist. +// It also returns diceerrors.ErrWrongTypeOperation if the object is not a bloom filter. func GetBloomFilter(key string, store *dstore.Store) (*Bloom, error) { obj := store.Get(key) if obj == nil { - return nil, nil + return nil, diceerrors.ErrKeyNotFound } if err := object.AssertType(obj.Type, object.ObjTypeBF); err != nil { return nil, diceerrors.ErrWrongTypeOperation @@ -304,19 +320,3 @@ func GetBloomFilter(key string, store *dstore.Store) (*Bloom, error) { return obj.Value.(*Bloom), nil } - -func CreateBloomFilter(key string, store *dstore.Store, opts *BloomOpts) (*Bloom, error) { - bf, err := GetBloomFilter(key, store) - if bf != nil { - return nil, diceerrors.ErrGeneral("item exists") - } - if err != nil { - return nil, err - } - if opts == nil { - opts = defaultBloomOpts() - } - obj := store.NewObj(newBloomFilter(opts), -1, object.ObjTypeBF) - store.Put(key, obj) - return obj.Value.(*Bloom), nil -} diff --git a/internal/eval/type_string.go b/internal/eval/type_string.go index 3553a00f5..8ab3f9938 100644 --- a/internal/eval/type_string.go +++ b/internal/eval/type_string.go @@ -8,14 +8,12 @@ import ( ) type String struct { - Value string - Type object.ObjectType + value string } func NewString(value string) *String { return &String{ - Value: value, - Type: object.ObjTypeString, + value: value, } } From f505f7dd7cd34649b11f23942ac066676ff33a74 Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Tue, 3 Dec 2024 15:38:55 +0530 Subject: [PATCH 05/25] Unit test fixes. Strangely mem utilization reduced. --- internal/eval/bloom_test.go | 2 +- internal/eval/eval_test.go | 6 +++--- internal/eval/type_string_test.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/eval/bloom_test.go b/internal/eval/bloom_test.go index 5ef929250..000499bd6 100644 --- a/internal/eval/bloom_test.go +++ b/internal/eval/bloom_test.go @@ -122,7 +122,7 @@ func TestUpdateIndexes(t *testing.T) { // Create a value, default opts and initialize all params of the filter value := "hello" opts := defaultBloomOpts() - bloom := newBloomFilter(opts) + bloom := NewBloom(opts) err := opts.updateIndexes(value) if err != nil { diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index 1ecab654c..5ba8b3f63 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -2995,7 +2995,7 @@ func testEvalPFADD(t *testing.T, store *dstore.Store) { name: "PFADD Incorrect type provided", setup: func() { key, value := "EXISTING_KEY", "VALUE" - oType := deduceType(value) + _, oType := getRawStringOrInt(value) var exDurationMs int64 = -1 keepttl := false @@ -4830,7 +4830,7 @@ func testEvalDebug(t *testing.T, store *dstore.Store) { store.Put(key, obj) }, input: []string{"MEMORY", "EXISTING_KEY"}, - migratedOutput: EvalResponse{Result: 89, Error: nil}, + migratedOutput: EvalResponse{Result: 72, Error: nil}, }, "root path": { @@ -4843,7 +4843,7 @@ func testEvalDebug(t *testing.T, store *dstore.Store) { store.Put(key, obj) }, input: []string{"MEMORY", "EXISTING_KEY", "$"}, - migratedOutput: EvalResponse{Result: 89, Error: nil}, + migratedOutput: EvalResponse{Result: 72, Error: nil}, }, "invalid path": { diff --git a/internal/eval/type_string_test.go b/internal/eval/type_string_test.go index 0fc2bf33a..57230ff89 100644 --- a/internal/eval/type_string_test.go +++ b/internal/eval/type_string_test.go @@ -13,7 +13,7 @@ func TestDeduceType(t *testing.T) { tests := []struct { name string input string - wantType uint8 + wantType object.ObjectType wantEnc uint8 }{ { @@ -45,7 +45,7 @@ func TestDeduceType(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - gotType := deduceType(tt.input) + _, gotType := getRawStringOrInt(tt.input) if gotType != tt.wantType { t.Errorf("deduceType(%q) = (%v), want (%v)", tt.input, gotType, tt.wantType) } From 6b9d3236c1afda2b7e3f222c7cb7fa9491186017 Mon Sep 17 00:00:00 2001 From: jujiale Date: Tue, 3 Dec 2024 18:49:27 +0800 Subject: [PATCH 06/25] fix: modify the config default value keep consistency (#1352) --- internal/cli/cli.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 36f80cf15..62820dec4 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -49,7 +49,7 @@ func printConfiguration() { // Add whether the watch feature is enabled slog.Info("running with", slog.Bool("profiling", config.DiceConfig.Performance.EnableProfiling)) - // Add whether the watch feature is enabled + // Add whether the persistence feature is enabled slog.Info("running with", slog.Bool("persistence", config.DiceConfig.Persistence.Enabled)) } @@ -73,10 +73,10 @@ func Execute() { flag.IntVar(&flagsConfig.RespServer.Port, "port", 7379, "port for the DiceDB server") - flag.IntVar(&flagsConfig.HTTP.Port, "http-port", 7380, "port for accepting requets over HTTP") + flag.IntVar(&flagsConfig.HTTP.Port, "http-port", 8082, "port for accepting requets over HTTP") flag.BoolVar(&flagsConfig.HTTP.Enabled, "enable-http", false, "enable DiceDB to listen, accept, and process HTTP") - flag.IntVar(&flagsConfig.WebSocket.Port, "websocket-port", 7381, "port for accepting requets over WebSocket") + flag.IntVar(&flagsConfig.WebSocket.Port, "websocket-port", 8379, "port for accepting requets over WebSocket") flag.BoolVar(&flagsConfig.WebSocket.Enabled, "enable-websocket", false, "enable DiceDB to listen, accept, and process WebSocket") flag.IntVar(&flagsConfig.Performance.NumShards, "num-shards", -1, "number shards to create. defaults to number of cores") @@ -98,7 +98,7 @@ func Execute() { flag.IntVar(&flagsConfig.Memory.KeysLimit, "keys-limit", config.DefaultKeysLimit, "keys limit for the DiceDB server. "+ "This flag controls the number of keys each shard holds at startup. You can multiply this number with the "+ "total number of shard threads to estimate how much memory will be required at system start up.") - flag.Float64Var(&flagsConfig.Memory.EvictionRatio, "eviction-ratio", 0.1, "ratio of keys to evict when the "+ + flag.Float64Var(&flagsConfig.Memory.EvictionRatio, "eviction-ratio", 0.9, "ratio of keys to evict when the "+ "keys limit is reached") flag.Usage = func() { @@ -115,9 +115,9 @@ func Execute() { fmt.Println(" -h, --help Show this help message") fmt.Println(" -host Host for the DiceDB server (default: \"0.0.0.0\")") fmt.Println(" -port Port for the DiceDB server (default: 7379)") - fmt.Println(" -http-port Port for accepting requests over HTTP (default: 7380)") + fmt.Println(" -http-port Port for accepting requests over HTTP (default: 8082)") fmt.Println(" -enable-http Enable DiceDB to listen, accept, and process HTTP (default: false)") - fmt.Println(" -websocket-port Port for accepting requests over WebSocket (default: 7381)") + fmt.Println(" -websocket-port Port for accepting requests over WebSocket (default: 8379)") fmt.Println(" -enable-websocket Enable DiceDB to listen, accept, and process WebSocket (default: false)") fmt.Println(" -num-shards Number of shards to create. Defaults to number of cores (default: -1)") fmt.Println(" -enable-watch Enable support for .WATCH commands and real-time reactivity (default: false)") @@ -130,8 +130,8 @@ func Execute() { fmt.Println(" -requirepass Enable authentication for the default user (default: \"\")") fmt.Println(" -o Directory path to create the config file (default: \"\")") fmt.Println(" -c File path of the config file (default: \"\")") - fmt.Println(" -keys-limit Keys limit for the DiceDB server (default: 0)") - fmt.Println(" -eviction-ratio Ratio of keys to evict when the keys limit is reached (default: 0.1)") + fmt.Println(" -keys-limit Keys limit for the DiceDB server (default: 200000000)") + fmt.Println(" -eviction-ratio Ratio of keys to evict when the keys limit is reached (default: 0.9)") color.Unset() os.Exit(0) } From a60515c17c910462b9c0d1dbc3b244d3bf5387ee Mon Sep 17 00:00:00 2001 From: Apoorv Yadav <32174554+apoorvyadav1111@users.noreply.github.com> Date: Tue, 3 Dec 2024 11:44:18 -0500 Subject: [PATCH 07/25] #1305: Add existing data types in Dump/ Restore (#1304) --- integration_tests/commands/resp/dump_test.go | 192 ++++++++++++++----- internal/eval/bloom.go | 115 ++++++++++- internal/eval/countminsketch.go | 80 ++++++++ internal/eval/deque.go | 159 +++++++++++++++ internal/eval/dump_restore.go | 156 +++++++++++++-- internal/eval/eval_test.go | 8 +- internal/eval/sortedset/sorted_set.go | 58 ++++++ internal/eval/store_eval.go | 2 +- 8 files changed, 695 insertions(+), 75 deletions(-) diff --git a/integration_tests/commands/resp/dump_test.go b/integration_tests/commands/resp/dump_test.go index 88f41ace4..27d50badb 100644 --- a/integration_tests/commands/resp/dump_test.go +++ b/integration_tests/commands/resp/dump_test.go @@ -1,7 +1,6 @@ package resp import ( - "encoding/base64" "testing" "github.com/dicedb/dice/testutils" @@ -11,7 +10,7 @@ import ( func TestDumpRestore(t *testing.T) { conn := getLocalConnection() defer conn.Close() - + simpleJSON := `{"name":"John","age":30}` testCases := []struct { name string commands []string @@ -20,57 +19,31 @@ func TestDumpRestore(t *testing.T) { { name: "DUMP and RESTORE string value", commands: []string{ - "SET mykey hello", - "DUMP mykey", - "DEL mykey", - "RESTORE mykey 2 CQAAAAAFaGVsbG//AEeXk742Rcc=", - "GET mykey", + "SET foo bar", + "DUMP foo", + "DEL foo", + "RESTORE foo 2 CQAAAAADYmFy/72GUVF+ClKv", + "GET foo", }, expected: []interface{}{ "OK", - func(result interface{}) bool { - dumped, ok := result.(string) - if !ok { - return false - } - decoded, err := base64.StdEncoding.DecodeString(dumped) - if err != nil { - return false - } - return len(decoded) > 11 && - decoded[0] == 0x09 && - decoded[1] == 0x00 && - string(decoded[6:11]) == "hello" && - decoded[11] == 0xFF - }, + "CQAAAAADYmFy/72GUVF+ClKv", int64(1), "OK", - "hello", + "bar", }, }, { name: "DUMP and RESTORE integer value", commands: []string{ - "SET intkey 42", - "DUMP intkey", - "DEL intkey", - "RESTORE intkey 2 CcAAAAAAAAAAKv9S/ymRDY3rXg==", + "set foo 12345", + "DUMP foo", + "DEL foo", + "RESTORE foo 2 CQUAAAAAAAAwOf8OqbusYAl2pQ==", }, expected: []interface{}{ "OK", - func(result interface{}) bool { - dumped, ok := result.(string) - if !ok { - return false - } - decoded, err := base64.StdEncoding.DecodeString(dumped) - if err != nil { - return false - } - return len(decoded) > 2 && - decoded[0] == 0x09 && - decoded[1] == 0xC0 - }, + "CQUAAAAAAAAwOf8OqbusYAl2pQ==", int64(1), "OK", }, @@ -84,26 +57,157 @@ func TestDumpRestore(t *testing.T) { "(nil)", }, }, + { + name: "DUMP JSON", + commands: []string{ + `JSON.SET foo $ ` + simpleJSON, + "DUMP foo", + "del foo", + "restore foo 2 CQMAAAAYeyJhZ2UiOjMwLCJuYW1lIjoiSm9obiJ9/6PVaIgw0n+C", + "JSON.GET foo $..name", + }, + expected: []interface{}{ + "OK", + "skip", + int64(1), + "OK", + `"John"`, + }, + }, + { + name: "DUMP Set", + commands: []string{ + "sadd foo bar baz bazz", + "dump foo", + "del foo", + "restore foo 2 CQYAAAAAAAAAAwAAAANiYXIAAAADYmF6AAAABGJhenr/DSf4vHxjdYo=", + "smembers foo", + }, + expected: []interface{}{ + int64(3), + "skip", + int64(1), + "OK", + []interface{}{"bar", "baz", "bazz"}, + }, + }, + { + name: "DUMP bytearray", + commands: []string{ + "setbit foo 1 1", + "dump foo", + "del foo", + "restore foo 2 CQQAAAAAAAAAAUD/g00L5pRbaJI=", + "get foo", + }, + expected: []interface{}{ + int64(0), + "CQQAAAAAAAAAAUD/g00L5pRbaJI=", + int64(1), + "OK", + "@", + }, + }, + { + name: "DUMP sorted set", + commands: []string{ + "zadd foo 1 bar 2 bazz", + "dump foo", + "del foo", + "restore foo 2 CQgAAAAAAAAAAgAAAAAAAAADYmFyP/AAAAAAAAAAAAAAAAAABGJhenpAAAAAAAAAAP/POOElibTuYQ==", + "zrange foo 0 2", + }, + expected: []interface{}{ + int64(2), + "skip", + int64(1), + "OK", + []interface{}{"bar", "bazz"}, + }, + }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - FireCommand(conn, "FLUSHALL") + FireCommand(conn, "del foo") for i, cmd := range tc.commands { result := FireCommand(conn, cmd) expected := tc.expected[i] - + if expected == "skip" { + // when order of elements define the dump value, we test the restore function and skip dump + continue + } switch exp := expected.(type) { case string: assert.Equal(t, exp, result) case []interface{}: assert.True(t, testutils.UnorderedEqual(exp, result)) - case func(interface{}) bool: - assert.True(t, exp(result), cmd) default: assert.Equal(t, expected, result) } } }) } + FireCommand(conn, "FLUSHDB") +} + +func TestDumpRestoreBF(t *testing.T) { + conn := getLocalConnection() + defer conn.Close() + res := FireCommand(conn, "bf.add foo bar") + assert.Equal(t, int64(1), res) + + dumpValue := FireCommand(conn, "dump foo") + FireCommand(conn, "del foo") + + res = FireCommand(conn, "restore foo 0 "+dumpValue.(string)) + assert.Equal(t, "OK", res) + res = FireCommand(conn, "bf.exists foo bazz") + assert.Equal(t, int64(0), res) + + FireCommand(conn, "FLUSHDB") +} + +func TestDumpRestoreCMS(t *testing.T) { + conn := getLocalConnection() + defer conn.Close() + + // Add a value to the CMS + FireCommand(conn, "CMS.INITBYPROB foo 0.1 0.01") + res := FireCommand(conn, "cms.incrby foo bar 42") + assert.Equal(t, []interface{}([]interface{}{int64(42)}), res) + + // Dump the serialized value + dumpValue := FireCommand(conn, "dump foo") + FireCommand(conn, "del foo") // Delete the CMS + + // Restore the CMS from the dumped value + res = FireCommand(conn, "restore foo 0 "+dumpValue.(string)) + assert.Equal(t, "OK", res) + + // Check the value for a key in the restored CMS + res = FireCommand(conn, "cms.query foo bar") + assert.Equal(t, []interface{}([]interface{}{int64(42)}), res) + + // Check that another key not in the CMS returns 0 + res = FireCommand(conn, "cms.query foo bar") + assert.Equal(t, []interface{}([]interface{}{int64(42)}), res) + + FireCommand(conn, "FLUSHDB") +} + +func TestDumpRestoreDeque(t *testing.T) { + conn := getLocalConnection() + defer conn.Close() + res := FireCommand(conn, "lpush foo bar") + assert.Equal(t, int64(1), res) + dumpValue := FireCommand(conn, "dump foo") + res = FireCommand(conn, "del foo") + assert.Equal(t, int64(1), res) + res = FireCommand(conn, "restore foo 0 "+dumpValue.(string)) + assert.Equal(t, "OK", res) + res = FireCommand(conn, "lpop foo") + assert.Equal(t, "bar", res) + + FireCommand(conn, "FLUSHDB") } diff --git a/internal/eval/bloom.go b/internal/eval/bloom.go index 35b893705..c4548e780 100644 --- a/internal/eval/bloom.go +++ b/internal/eval/bloom.go @@ -1,6 +1,8 @@ package eval import ( + "bytes" + "encoding/binary" "fmt" "hash" "math" @@ -50,6 +52,8 @@ type BloomOpts struct { // is under the assumption that it's consumed at only 1 place at a time. Add // a lock when multiple clients can be supported. indexes []uint64 + + hashFnsSeeds []uint64 // seed for hash functions } type Bloom struct { @@ -102,10 +106,11 @@ func newBloomFilter(opts *BloomOpts) *Bloom { // k = ceil(ln(2) * bpe) k := math.Ceil(ln2 * opts.bpe) opts.hashFns = make([]hash.Hash64, int(k)) - + opts.hashFnsSeeds = make([]uint64, int(k)) // Initialize hash functions with random seeds for i := 0; i < int(k); i++ { - opts.hashFns[i] = murmur3.SeedNew64(rand.Uint64()) //nolint:gosec + opts.hashFnsSeeds[i] = rand.Uint64() //nolint:gosec + opts.hashFns[i] = murmur3.SeedNew64(opts.hashFnsSeeds[i]) } // initialize the common slice for storing indexes of bits to be set @@ -115,15 +120,15 @@ func newBloomFilter(opts *BloomOpts) *Bloom { // bits = k * entries / ln(2) // bytes = bits * 8 bits := uint64(math.Ceil((k * float64(opts.capacity)) / ln2)) - var bytes uint64 + var bytesNeeded uint64 if bits%8 == 0 { - bytes = bits / 8 + bytesNeeded = bits / 8 } else { - bytes = (bits / 8) + 1 + bytesNeeded = (bits / 8) + 1 } - opts.bits = bytes * 8 + opts.bits = bytesNeeded * 8 - bitset := make([]byte, bytes) + bitset := make([]byte, bytesNeeded) return &Bloom{opts, bitset, 0} } @@ -320,3 +325,99 @@ func CreateBloomFilter(key string, store *dstore.Store, opts *BloomOpts) (*Bloom store.Put(key, obj) return obj.Value.(*Bloom), nil } + +func (b *Bloom) Serialize(buf *bytes.Buffer) error { + // Serialize the Bloom struct + if err := binary.Write(buf, binary.BigEndian, b.cnt); err != nil { + return err + } + if err := binary.Write(buf, binary.BigEndian, b.opts.errorRate); err != nil { + return err + } + if err := binary.Write(buf, binary.BigEndian, b.opts.capacity); err != nil { + return err + } + if err := binary.Write(buf, binary.BigEndian, b.opts.bits); err != nil { + return err + } + + // Serialize the number of seeds and the seeds themselves + numSeeds := uint64(len(b.opts.hashFnsSeeds)) + if err := binary.Write(buf, binary.BigEndian, numSeeds); err != nil { + return err + } + if err := binary.Write(buf, binary.BigEndian, b.opts.hashFnsSeeds); err != nil { + return err + } + + // Serialize the number of indexes and the indexes themselves + numIndexes := uint64(len(b.opts.indexes)) + if err := binary.Write(buf, binary.BigEndian, numIndexes); err != nil { + return err + } + if err := binary.Write(buf, binary.BigEndian, b.opts.indexes); err != nil { + return err + } + + // Serialize the bitset + if _, err := buf.Write(b.bitset); err != nil { + return err + } + + return nil +} + +func DeserializeBloom(buf *bytes.Reader) (*Bloom, error) { + bloom := &Bloom{ + opts: &BloomOpts{}, // Initialize the opts field to prevent nil pointer dereference + } + + // Deserialize the Bloom struct + if err := binary.Read(buf, binary.BigEndian, &bloom.cnt); err != nil { + return nil, err + } + if err := binary.Read(buf, binary.BigEndian, &bloom.opts.errorRate); err != nil { + return nil, err + } + if err := binary.Read(buf, binary.BigEndian, &bloom.opts.capacity); err != nil { + return nil, err + } + if err := binary.Read(buf, binary.BigEndian, &bloom.opts.bits); err != nil { + return nil, err + } + + // Deserialize hash function seeds + var numSeeds uint64 + if err := binary.Read(buf, binary.BigEndian, &numSeeds); err != nil { + return nil, err + } + bloom.opts.hashFnsSeeds = make([]uint64, numSeeds) + if err := binary.Read(buf, binary.BigEndian, &bloom.opts.hashFnsSeeds); err != nil { + return nil, err + } + + // Deserialize indexes + var numIndexes uint64 + if err := binary.Read(buf, binary.BigEndian, &numIndexes); err != nil { + return nil, err + } + bloom.opts.indexes = make([]uint64, numIndexes) + if err := binary.Read(buf, binary.BigEndian, &bloom.opts.indexes); err != nil { + return nil, err + } + + // Deserialize bitset + bloom.bitset = make([]byte, bloom.opts.bits) + if _, err := buf.Read(bloom.bitset); err != nil { + return nil, err + } + + // Recalculate derived values + bloom.opts.bpe = -1 * math.Log(bloom.opts.errorRate) / math.Ln2 + bloom.opts.hashFns = make([]hash.Hash64, len(bloom.opts.hashFnsSeeds)) + for i := 0; i < len(bloom.opts.hashFnsSeeds); i++ { + bloom.opts.hashFns[i] = murmur3.SeedNew64(bloom.opts.hashFnsSeeds[i]) + } + + return bloom, nil +} diff --git a/internal/eval/countminsketch.go b/internal/eval/countminsketch.go index 27e417851..80a564631 100644 --- a/internal/eval/countminsketch.go +++ b/internal/eval/countminsketch.go @@ -1,7 +1,9 @@ package eval import ( + "bytes" "encoding/binary" + "errors" "fmt" "hash" "hash/fnv" @@ -232,6 +234,84 @@ func (c *CountMinSketch) mergeMatrices(sources []*CountMinSketch, weights []uint } } +// serialize encodes the CountMinSketch into a byte slice. +func (c *CountMinSketch) serialize(buffer *bytes.Buffer) error { + if c == nil { + return errors.New("cannot serialize a nil CountMinSketch") + } + + // Write depth, width, and count + if err := binary.Write(buffer, binary.BigEndian, c.opts.depth); err != nil { + return err + } + if err := binary.Write(buffer, binary.BigEndian, c.opts.width); err != nil { + return err + } + if err := binary.Write(buffer, binary.BigEndian, c.count); err != nil { + return err + } + + // Write matrix + for i := 0; i < len(c.matrix); i++ { + for j := 0; j < len(c.matrix[i]); j++ { + if err := binary.Write(buffer, binary.BigEndian, c.matrix[i][j]); err != nil { + return err + } + } + } + + return nil +} + +// deserialize reconstructs a CountMinSketch from a byte slice. +func DeserializeCMS(buffer *bytes.Reader) (*CountMinSketch, error) { + if buffer.Len() < 24 { // Minimum size for depth, width, and count + return nil, errors.New("insufficient data for deserialization") + } + + var depth, width, count uint64 + + // Read depth, width, and count + if err := binary.Read(buffer, binary.BigEndian, &depth); err != nil { + return nil, err + } + if err := binary.Read(buffer, binary.BigEndian, &width); err != nil { + return nil, err + } + if err := binary.Read(buffer, binary.BigEndian, &count); err != nil { + return nil, err + } + fmt.Println(depth, width, count, buffer.Len()) + // Validate data size + expectedSize := int(depth * width * 8) // Each uint64 takes 8 bytes + if buffer.Len() <= expectedSize { + return nil, errors.New("data size mismatch with expected matrix size") + } + + // Read matrix + matrix := make([][]uint64, depth) + for i := 0; i < int(depth); i++ { + matrix[i] = make([]uint64, width) + for j := 0; j < int(width); j++ { + if err := binary.Read(buffer, binary.BigEndian, &matrix[i][j]); err != nil { + return nil, err + } + } + } + + opts := &CountMinSketchOpts{ + depth: depth, + width: width, + hasher: fnv.New64(), // Default hasher + } + + return &CountMinSketch{ + opts: opts, + matrix: matrix, + count: count, + }, nil +} + // evalCMSMerge is used to merge multiple sketches into one. The final sketch // contains the weighted sum of the values in each of the source sketches. If // weights are not provided, default is 1. diff --git a/internal/eval/deque.go b/internal/eval/deque.go index 59d755c5f..2bf8c7d65 100644 --- a/internal/eval/deque.go +++ b/internal/eval/deque.go @@ -1,6 +1,8 @@ package eval import ( + "bytes" + "encoding/binary" "errors" "fmt" "strconv" @@ -838,3 +840,160 @@ func DecodeDeqEntry(xb []byte) (x string, entryLen int) { val >>= 64 - bit return strconv.FormatInt(val, 10), entryLen } + +func (q *Deque) Serialize(buf *bytes.Buffer) error { + if q == nil { + return errors.New("deque is nil") + } + + err := binary.Write(buf, binary.BigEndian, q.Length) + if err != nil { + return err + } + err = binary.Write(buf, binary.BigEndian, int32(q.leftIdx)) + if err != nil { + return err + } + + // Serialize byteList + err = serializeByteList(buf, q.list) + if err != nil { + return err + } + + return nil +} + +func serializeByteList(buf *bytes.Buffer, list *byteList) error { + if list == nil { + return binary.Write(buf, binary.BigEndian, int32(0)) + } + + err := binary.Write(buf, binary.BigEndian, int32(list.bufLen)) + if err != nil { + return err + } + err = binary.Write(buf, binary.BigEndian, list.size) + if err != nil { + return err + } + + current := list.head + var nodeCount int32 + nodes := [][]byte{} + + for current != nil { + nodes = append(nodes, current.buf) + current = current.next + nodeCount++ + } + + err = binary.Write(buf, binary.BigEndian, nodeCount) + if err != nil { + return err + } + + for _, nodeBuf := range nodes { + err = binary.Write(buf, binary.BigEndian, int32(len(nodeBuf))) + if err != nil { + return err + } + _, err = buf.Write(nodeBuf) + if err != nil { + return err + } + } + + return nil +} + +func DeserializeDeque(buf *bytes.Reader) (*Deque, error) { + if buf.Len() == 0 { + return nil, errors.New("data is empty") + } + + var length int64 + var leftIdx int32 + + err := binary.Read(buf, binary.BigEndian, &length) + if err != nil { + return nil, err + } + + err = binary.Read(buf, binary.BigEndian, &leftIdx) + if err != nil { + return nil, err + } + + list, err := deserializeByteList(buf) + if err != nil { + return nil, err + } + + return &Deque{ + Length: length, + list: list, + leftIdx: int(leftIdx), + }, nil +} + +func deserializeByteList(buf *bytes.Reader) (*byteList, error) { + var bufLen int32 + var size int64 + var nodeCount int32 + + err := binary.Read(buf, binary.BigEndian, &bufLen) + if err != nil { + return nil, err + } + + err = binary.Read(buf, binary.BigEndian, &size) + if err != nil { + return nil, err + } + + // Read the number of nodes + err = binary.Read(buf, binary.BigEndian, &nodeCount) + if err != nil { + return nil, err + } + + // Reconstruct the nodes + var prev *byteListNode + list := &byteList{ + bufLen: int(bufLen), + size: size, + } + + for i := int32(0); i < nodeCount; i++ { + // Read the length of the buffer + var bufSize int32 + err := binary.Read(buf, binary.BigEndian, &bufSize) + if err != nil { + return nil, err + } + + // Read the buffer data + nodeBuf := make([]byte, bufSize) + _, err = buf.Read(nodeBuf) + if err != nil { + return nil, err + } + + // Create and link the node + node := &byteListNode{ + buf: nodeBuf, + prev: prev, + } + if prev == nil { + list.head = node + } else { + prev.next = node + } + prev = node + } + + list.tail = prev + + return list, nil +} diff --git a/internal/eval/dump_restore.go b/internal/eval/dump_restore.go index 29d87159d..5c1b39953 100644 --- a/internal/eval/dump_restore.go +++ b/internal/eval/dump_restore.go @@ -3,9 +3,11 @@ package eval import ( "bytes" "encoding/binary" + "encoding/json" "errors" "hash/crc64" + "github.com/dicedb/dice/internal/eval/sortedset" "github.com/dicedb/dice/internal/object" ) @@ -13,19 +15,62 @@ func rdbDeserialize(data []byte) (*object.Obj, error) { if len(data) < 3 { return nil, errors.New("insufficient data for deserialization") } - objType := data[1] + var value interface{} + var err error + var valueRaw interface{} + + buf := bytes.NewReader(data) + _, err = buf.ReadByte() + if err != nil { + return nil, err + } + objType, err := buf.ReadByte() + if err != nil { + return nil, err + } switch objType { - case 0x00: - return readString(data[2:]) - case 0xC0: // Integer type - return readInt(data[2:]) + case object.ObjTypeString: + value, err = readString(buf) + case object.ObjTypeInt: // Integer type + value, err = readInt(buf) + case object.ObjTypeSet: // Set type + value, err = readSet(buf) + case object.ObjTypeJSON: // JSON type + valueRaw, err = readString(buf) + if err := json.Unmarshal([]byte(valueRaw.(string)), &value); err != nil { + return nil, err + } + case object.ObjTypeByteArray: // Byte array type + valueRaw, err = readInt(buf) + if err != nil { + return nil, err + } + byteArray := &ByteArray{ + Length: valueRaw.(int64), + data: make([]byte, valueRaw.(int64)), + } + if _, err := buf.Read(byteArray.data); err != nil { + return nil, err + } + value = byteArray + case object.ObjTypeDequeue: // Byte list type (Deque) + value, err = DeserializeDeque(buf) + case object.ObjTypeBF: // Bloom filter type + value, err = DeserializeBloom(buf) + case object.ObjTypeSortedSet: + value, err = sortedset.DeserializeSortedSet(buf) + case object.ObjTypeCountMinSketch: + value, err = DeserializeCMS(buf) default: return nil, errors.New("unsupported object type") } + if err != nil { + return nil, err + } + return &object.Obj{Type: objType, Value: value}, nil } -func readString(data []byte) (*object.Obj, error) { - buf := bytes.NewReader(data) +func readString(buf *bytes.Reader) (interface{}, error) { var strLen uint32 if err := binary.Read(buf, binary.BigEndian, &strLen); err != nil { return nil, err @@ -36,29 +81,44 @@ func readString(data []byte) (*object.Obj, error) { return nil, err } - return &object.Obj{Type: object.ObjTypeString, Value: string(strBytes)}, nil + return string(strBytes), nil } -func readInt(data []byte) (*object.Obj, error) { +func readInt(buf *bytes.Reader) (interface{}, error) { var intVal int64 - if err := binary.Read(bytes.NewReader(data), binary.BigEndian, &intVal); err != nil { + if err := binary.Read(buf, binary.BigEndian, &intVal); err != nil { return nil, err } - return &object.Obj{Type: object.ObjTypeInt, Value: intVal}, nil + return intVal, nil +} + +func readSet(buf *bytes.Reader) (interface{}, error) { + var strLen uint64 + if err := binary.Read(buf, binary.BigEndian, &strLen); err != nil { + return nil, err + } + setItems := make(map[string]struct{}) + for i := 0; i < int(strLen); i++ { + value, err := readString(buf) + if err != nil { + return nil, err + } + setItems[value.(string)] = struct{}{} + } + return setItems, nil } func rdbSerialize(obj *object.Obj) ([]byte, error) { var buf bytes.Buffer buf.WriteByte(0x09) - + buf.WriteByte(obj.Type) switch obj.Type { case object.ObjTypeString: str, ok := obj.Value.(string) if !ok { return nil, errors.New("invalid string value") } - buf.WriteByte(0x00) if err := writeString(&buf, str); err != nil { return nil, err } @@ -68,15 +128,67 @@ func rdbSerialize(obj *object.Obj) ([]byte, error) { if !ok { return nil, errors.New("invalid integer value") } - buf.WriteByte(0xC0) writeInt(&buf, intVal) - + case object.ObjTypeSet: + setItems, ok := obj.Value.(map[string]struct{}) + if !ok { + return nil, errors.New("invalid set value") + } + if err := writeSet(&buf, setItems); err != nil { + return nil, err + } + case object.ObjTypeJSON: + jsonValue, err := json.Marshal(obj.Value) + if err != nil { + return nil, err + } + if err := writeString(&buf, string(jsonValue)); err != nil { + return nil, err + } + case object.ObjTypeByteArray: + byteArray, ok := obj.Value.(*ByteArray) + if !ok { + return nil, errors.New("invalid byte array value") + } + writeInt(&buf, byteArray.Length) + buf.Write(byteArray.data) + case object.ObjTypeDequeue: + deque, ok := obj.Value.(*Deque) + if !ok { + return nil, errors.New("invalid byte list value") + } + if err := deque.Serialize(&buf); err != nil { + return nil, err + } + case object.ObjTypeBF: + bitSet, ok := obj.Value.(*Bloom) + if !ok { + return nil, errors.New("invalid bloom filter value") + } + if err := bitSet.Serialize(&buf); err != nil { + return nil, err + } + case object.ObjTypeSortedSet: + sortedSet, ok := obj.Value.(*sortedset.Set) + if !ok { + return nil, errors.New("invalid sorted set value") + } + if err := sortedSet.Serialize(&buf); err != nil { + return nil, err + } + case object.ObjTypeCountMinSketch: + cms, ok := obj.Value.(*CountMinSketch) + if !ok { + return nil, errors.New("invalid countminsketch value") + } + if err := cms.serialize(&buf); err != nil { + return nil, err + } default: return nil, errors.New("unsupported object type") } buf.WriteByte(0xFF) // End marker - return appendChecksum(buf.Bytes()), nil } @@ -95,6 +207,18 @@ func writeInt(buf *bytes.Buffer, intVal int64) { buf.Write(tempBuf) } +func writeSet(buf *bytes.Buffer, setItems map[string]struct{}) error { + setLen := uint64(len(setItems)) + if err := binary.Write(buf, binary.BigEndian, setLen); err != nil { + return err + } + for item := range setItems { + if err := writeString(buf, item); err != nil { + return err + } + } + return nil +} func appendChecksum(data []byte) []byte { checksum := crc64.Checksum(data, crc64.MakeTable(crc64.ECMA)) checksumBuf := make([]byte, 8) diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index 61ae149fe..01be7f591 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -8107,13 +8107,7 @@ func testEvalDUMP(t *testing.T, store *dstore.Store) { }, input: []string{"INTEGER_KEY"}, migratedOutput: EvalResponse{ - Result: base64.StdEncoding.EncodeToString([]byte{ - 0x09, - 0xC0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, - 0xFF, - 0x12, 0x77, 0xDE, 0x29, 0x53, 0xDB, 0x44, 0xC2, - }), + Result: "CQUAAAAAAAAACv9+l81XgsShqw==", Error: nil, }, }, diff --git a/internal/eval/sortedset/sorted_set.go b/internal/eval/sortedset/sorted_set.go index 51d64efd5..5b4435c3f 100644 --- a/internal/eval/sortedset/sorted_set.go +++ b/internal/eval/sortedset/sorted_set.go @@ -1,6 +1,8 @@ package sortedset import ( + "bytes" + "encoding/binary" "strconv" "strings" @@ -251,3 +253,59 @@ func (ss *Set) CountInRange(minVal, maxVal float64) int { return count } + +func (ss *Set) Serialize(buf *bytes.Buffer) error { + // Serialize the length of the memberMap + memberCount := uint64(len(ss.memberMap)) + if err := binary.Write(buf, binary.BigEndian, memberCount); err != nil { + return err + } + + // Serialize each member and its score + for member, score := range ss.memberMap { + memberLen := uint64(len(member)) + if err := binary.Write(buf, binary.BigEndian, memberLen); err != nil { + return err + } + if _, err := buf.WriteString(member); err != nil { + return err + } + if err := binary.Write(buf, binary.BigEndian, score); err != nil { + return err + } + } + return nil +} + +func DeserializeSortedSet(buf *bytes.Reader) (*Set, error) { + ss := New() + + // Read the member count + var memberCount uint64 + if err := binary.Read(buf, binary.BigEndian, &memberCount); err != nil { + return nil, err + } + + // Read each member and its score + for i := uint64(0); i < memberCount; i++ { + var memberLen uint64 + if err := binary.Read(buf, binary.BigEndian, &memberLen); err != nil { + return nil, err + } + + member := make([]byte, memberLen) + if _, err := buf.Read(member); err != nil { + return nil, err + } + + var score float64 + if err := binary.Read(buf, binary.BigEndian, &score); err != nil { + return nil, err + } + + // Add the member back to the set + ss.Upsert(score, string(member)) + } + + return ss, nil +} diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 37b694f5e..756201b95 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -2630,6 +2630,7 @@ func evalDUMP(args []string, store *dstore.Store) *EvalResponse { serializedValue, err := rdbSerialize(obj) if err != nil { + fmt.Println("error", err) return makeEvalError(diceerrors.ErrGeneral("serialization failed")) } encodedResult := base64.StdEncoding.EncodeToString(serializedValue) @@ -2651,7 +2652,6 @@ func evalRestore(args []string, store *dstore.Store) *EvalResponse { if err != nil { return makeEvalError(diceerrors.ErrGeneral("failed to decode base64 value")) } - obj, err := rdbDeserialize(serializedData) if err != nil { return makeEvalError(diceerrors.ErrGeneral("deserialization failed")) From 6aae69b61fbedcc86d4d48f1fd5f1e393f0d7aa3 Mon Sep 17 00:00:00 2001 From: rahul-mallick-15 <88314273+rahul-mallick-15@users.noreply.github.com> Date: Tue, 3 Dec 2024 22:35:19 +0530 Subject: [PATCH 08/25] Remove --enable-multithreading flag usage in README (#1349) --- README.md | 6 +++--- docs/src/content/docs/get-started/installation.mdx | 2 +- docs/src/content/docs/get-started/reactive-hello-world.mdx | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index c3845f361..2335c52bb 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ Although DiceDB is a drop-in replacement of Redis, which means almost no learnin The easiest way to get started with DiceDB is using [Docker](https://www.docker.com/) by running the following command. ```bash -docker run -p 7379:7379 dicedb/dicedb --enable-multithreading --enable-watch +docker run -p 7379:7379 dicedb/dicedb --enable-watch ``` The above command will start the DiceDB server running locally on the port `7379` and you can connect @@ -60,10 +60,10 @@ To run DiceDB for local development or running from source, you will need ```bash git clone https://github.com/dicedb/dice cd dice -go run main.go --enable-multithreading --enable-watch +go run main.go --enable-watch ``` -You can skip passing the two flags if you are not working with multi-threading or `.WATCH` features. +You can skip passing the flag if you are not working with `.WATCH` feature. 1. Install GoLangCI diff --git a/docs/src/content/docs/get-started/installation.mdx b/docs/src/content/docs/get-started/installation.mdx index 75f9622b2..8ba500b4e 100644 --- a/docs/src/content/docs/get-started/installation.mdx +++ b/docs/src/content/docs/get-started/installation.mdx @@ -16,7 +16,7 @@ We are looking for Early Design Partners, so, if you want to evaluate DiceDB, [b The easiest way to get started with DiceDB is using [Docker](https://www.docker.com/) by running the following command. ```bash -docker run -p 7379:7379 dicedb/dicedb --enable-multithreading --enable-watch +docker run -p 7379:7379 dicedb/dicedb --enable-watch ``` The above command will start the DiceDB server running locally on the port `7379` and you can connect diff --git a/docs/src/content/docs/get-started/reactive-hello-world.mdx b/docs/src/content/docs/get-started/reactive-hello-world.mdx index 744c56866..badd81fed 100644 --- a/docs/src/content/docs/get-started/reactive-hello-world.mdx +++ b/docs/src/content/docs/get-started/reactive-hello-world.mdx @@ -15,12 +15,12 @@ But, before we start, make sure you have ### Starting DiceDB -Start the DiceDB server with the two flags `--enable-multithreading` and `--enable-watch` -to enable multi-threading and watch mode, respectively. Your command would look something +Start the DiceDB server with the flag `--enable-watch` +to enable watch mode. Your command would look something like this ```bash -docker run -p 7379:7379 dicedb/dicedb --enable-multithreading --enable-watch +docker run -p 7379:7379 dicedb/dicedb --enable-watch ``` Also, connect to the database using the CLI as mentioned in the above installation steps or From 531a32a0cdb391b044059ccb1a73c96f19e67395 Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Wed, 4 Dec 2024 16:50:30 +0530 Subject: [PATCH 09/25] Some errors as constants and bloom -> bloomfilter --- integration_tests/commands/http/bloom_test.go | 7 ++++--- integration_tests/commands/http/jsondebug_test.go | 2 +- integration_tests/commands/resp/bloom_test.go | 7 ++++--- integration_tests/commands/websocket/bloom_test.go | 7 ++++--- integration_tests/commands/websocket/jsondebug_test.go | 2 +- internal/errors/migrated_errors.go | 1 + internal/eval/bloom_test.go | 2 +- internal/eval/eval_test.go | 2 +- internal/eval/store_eval.go | 6 ++++-- internal/eval/{type_bloom.go => type_bloomfilter.go} | 4 ++-- 10 files changed, 23 insertions(+), 17 deletions(-) rename internal/eval/{type_bloom.go => type_bloomfilter.go} (99%) diff --git a/integration_tests/commands/http/bloom_test.go b/integration_tests/commands/http/bloom_test.go index d6c47e41b..40c1de24a 100644 --- a/integration_tests/commands/http/bloom_test.go +++ b/integration_tests/commands/http/bloom_test.go @@ -3,6 +3,7 @@ package http import ( "testing" + diceerrors "github.com/dicedb/dice/internal/errors" "github.com/stretchr/testify/assert" ) @@ -82,7 +83,7 @@ func TestBloomFilter(t *testing.T) { Body: map[string]interface{}{"key": "bf", "values": []interface{}{0.01, 2000}}, }, }, - expected: []interface{}{"OK", "ERR item exists"}, + expected: []interface{}{"OK", diceerrors.ErrKeyExists}, }, } @@ -199,7 +200,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { Body: map[string]interface{}{"key": "bf"}, }, }, - expected: []interface{}{"ERR not found"}, + expected: []interface{}{diceerrors.ErrKeyNotFound}, }, { name: "BF.RESERVE with a very high error rate", @@ -281,7 +282,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { Body: map[string]interface{}{"key": "bf", "values": []interface{}{0.01, 2000}}, }, }, - expected: []interface{}{"OK", "ERR item exists"}, + expected: []interface{}{"OK", diceerrors.ErrKeyExists}, }, { name: "BF.INFO after multiple additions", diff --git a/integration_tests/commands/http/jsondebug_test.go b/integration_tests/commands/http/jsondebug_test.go index 26db95c84..37ab3a061 100644 --- a/integration_tests/commands/http/jsondebug_test.go +++ b/integration_tests/commands/http/jsondebug_test.go @@ -16,7 +16,7 @@ func TestJSONDEBUG(t *testing.T) { {Command: "JSON.SET", Body: map[string]interface{}{"key": "k1", "path": "$", "json": map[string]interface{}{"a": 1}}}, {Command: "JSON.DEBUG", Body: map[string]interface{}{"values": []interface{}{"MEMORY", "k1"}}}, }, - expected: []interface{}{"OK", float64(89)}, + expected: []interface{}{"OK", float64(72)}, }, { name: "jsondebug with a valid path", diff --git a/integration_tests/commands/resp/bloom_test.go b/integration_tests/commands/resp/bloom_test.go index 53ba8b506..e01c0b091 100644 --- a/integration_tests/commands/resp/bloom_test.go +++ b/integration_tests/commands/resp/bloom_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + diceerrors "github.com/dicedb/dice/internal/errors" "github.com/stretchr/testify/assert" ) @@ -42,7 +43,7 @@ func TestBFReserveAddInfoExists(t *testing.T) { { name: "BF.RESERVE on existent filter returns error", cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 1000"}, - expect: []interface{}{"OK", "ERR item exists"}, + expect: []interface{}{"OK", diceerrors.ErrKeyExists}, delays: []time.Duration{0, 0}, cleanUp: []string{"DEL bf"}, }, @@ -135,7 +136,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { { name: "BF.INFO on a non-existent filter", cmds: []string{"BF.INFO bf"}, - expect: []interface{}{"ERR not found"}, + expect: []interface{}{diceerrors.ErrKeyNotFound}, delays: []time.Duration{0}, cleanUp: []string{"del bf"}, }, @@ -170,7 +171,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { { name: "BF.RESERVE with duplicate filter name", cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 2000"}, - expect: []interface{}{"OK", "ERR item exists"}, + expect: []interface{}{"OK", diceerrors.ErrKeyExists}, delays: []time.Duration{0, 0}, cleanUp: []string{"del bf"}, }, diff --git a/integration_tests/commands/websocket/bloom_test.go b/integration_tests/commands/websocket/bloom_test.go index 7198505df..ba250fa95 100644 --- a/integration_tests/commands/websocket/bloom_test.go +++ b/integration_tests/commands/websocket/bloom_test.go @@ -4,6 +4,7 @@ import ( "testing" "time" + diceerrors "github.com/dicedb/dice/internal/errors" "github.com/stretchr/testify/assert" ) @@ -37,7 +38,7 @@ func TestBFReserveAddInfoExists(t *testing.T) { { name: "BF.RESERVE on existent filter returns error", cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 1000"}, - expect: []interface{}{"OK", "ERR item exists"}, + expect: []interface{}{"OK", diceerrors.ErrKeyExists}, cleanUp: []string{"DEL bf"}, }, } @@ -126,7 +127,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { { name: "BF.INFO on a non-existent filter", cmds: []string{"BF.INFO bf"}, - expect: []interface{}{"ERR not found"}, + expect: []interface{}{diceerrors.ErrKeyNotFound}, delays: []time.Duration{0}, cleanUp: []string{"del bf"}, }, @@ -161,7 +162,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { { name: "BF.RESERVE with duplicate filter name", cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 2000"}, - expect: []interface{}{"OK", "ERR item exists"}, + expect: []interface{}{"OK", diceerrors.ErrKeyExists}, delays: []time.Duration{0, 0}, cleanUp: []string{"del bf"}, }, diff --git a/integration_tests/commands/websocket/jsondebug_test.go b/integration_tests/commands/websocket/jsondebug_test.go index 8f2cba904..77a805f69 100644 --- a/integration_tests/commands/websocket/jsondebug_test.go +++ b/integration_tests/commands/websocket/jsondebug_test.go @@ -30,7 +30,7 @@ func TestJSONDEBUG(t *testing.T) { `JSON.SET k1 $ {"a":1}`, "JSON.DEBUG MEMORY k1", }, - expected: []interface{}{"OK", float64(89)}, + expected: []interface{}{"OK", float64(72)}, }, { name: "jsondebug with a valid path", diff --git a/internal/errors/migrated_errors.go b/internal/errors/migrated_errors.go index 6c8fe4e4c..ea81b0c4e 100644 --- a/internal/errors/migrated_errors.go +++ b/internal/errors/migrated_errors.go @@ -33,6 +33,7 @@ var ( ErrInvalidIPAddress = errors.New("invalid IP address") ErrInvalidFingerprint = errors.New("invalid fingerprint") ErrKeyDoesNotExist = errors.New("ERR could not perform this operation on a key that doesn't exist") + ErrKeyExists = errors.New("ERR key exists") // Error generation functions for specific error messages with dynamic parameters. ErrWrongArgumentCount = func(command string) error { diff --git a/internal/eval/bloom_test.go b/internal/eval/bloom_test.go index 000499bd6..d88d97f2f 100644 --- a/internal/eval/bloom_test.go +++ b/internal/eval/bloom_test.go @@ -122,7 +122,7 @@ func TestUpdateIndexes(t *testing.T) { // Create a value, default opts and initialize all params of the filter value := "hello" opts := defaultBloomOpts() - bloom := NewBloom(opts) + bloom := NewBloomFilter(opts) err := opts.updateIndexes(value) if err != nil { diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index 5ba8b3f63..22089ddf6 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -9028,7 +9028,7 @@ func testEvalBFINFO(t *testing.T, store *dstore.Store) { { name: "BF.INFO on non-existent filter", input: []string{"nonExistentFilter"}, - migratedOutput: EvalResponse{Result: nil, Error: errors.New("ERR not found")}, + migratedOutput: EvalResponse{Result: nil, Error: diceerrors.ErrKeyNotFound}, }, } diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 343a386e4..c58a63008 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -2869,13 +2869,15 @@ func evalBFRESERVE(args []string, store *dstore.Store) *EvalResponse { key := args[0] - _, err = GetBloomFilter(key, store) + bf, err := GetBloomFilter(key, store) if err != nil && err != diceerrors.ErrKeyNotFound { // bloom filter does not exist return makeEvalError(err) } else if err != nil && err == diceerrors.ErrKeyNotFound { // key does not exists CreateOrReplaceBloomFilter(key, opts, store) return makeEvalResult(clientio.OK) - } else { // bloom filter already exists + } else if bf != nil { // bloom filter already exists + return makeEvalError(diceerrors.ErrKeyExists) + } else { return makeEvalResult(clientio.OK) } } diff --git a/internal/eval/type_bloom.go b/internal/eval/type_bloomfilter.go similarity index 99% rename from internal/eval/type_bloom.go rename to internal/eval/type_bloomfilter.go index 3d7a6072c..816524cad 100644 --- a/internal/eval/type_bloom.go +++ b/internal/eval/type_bloomfilter.go @@ -92,7 +92,7 @@ func newBloomOpts(args []string) (*BloomOpts, error) { // newBloomFilter creates and returns a new filter. It is responsible for initializing the // underlying bit array. -func NewBloom(opts *BloomOpts) *Bloom { +func NewBloomFilter(opts *BloomOpts) *Bloom { // Calculate bits per element // bpe = -log(errorRate)/ln(2)^2 num := -1 * math.Log(opts.errorRate) @@ -285,7 +285,7 @@ func CreateOrReplaceBloomFilter(key string, opts *BloomOpts, store *dstore.Store if opts == nil { opts = defaultBloomOpts() } - bf := NewBloom(opts) + bf := NewBloomFilter(opts) obj := store.NewObj(bf, -1, object.ObjTypeBF) store.Put(key, obj) return bf From 32e86d00eb557d2b21e360d6167d3da8f2ca605c Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Wed, 4 Dec 2024 17:01:56 +0530 Subject: [PATCH 10/25] Integration tests fixes --- integration_tests/commands/http/bloom_test.go | 6 +++--- integration_tests/commands/resp/bloom_test.go | 6 +++--- integration_tests/commands/resp/jsondebug_test.go | 2 +- integration_tests/commands/websocket/bloom_test.go | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/integration_tests/commands/http/bloom_test.go b/integration_tests/commands/http/bloom_test.go index 40c1de24a..8d28958b9 100644 --- a/integration_tests/commands/http/bloom_test.go +++ b/integration_tests/commands/http/bloom_test.go @@ -83,7 +83,7 @@ func TestBloomFilter(t *testing.T) { Body: map[string]interface{}{"key": "bf", "values": []interface{}{0.01, 2000}}, }, }, - expected: []interface{}{"OK", diceerrors.ErrKeyExists}, + expected: []interface{}{"OK", diceerrors.ErrKeyExists.Error()}, }, } @@ -200,7 +200,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { Body: map[string]interface{}{"key": "bf"}, }, }, - expected: []interface{}{diceerrors.ErrKeyNotFound}, + expected: []interface{}{diceerrors.ErrKeyNotFound.Error()}, }, { name: "BF.RESERVE with a very high error rate", @@ -282,7 +282,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { Body: map[string]interface{}{"key": "bf", "values": []interface{}{0.01, 2000}}, }, }, - expected: []interface{}{"OK", diceerrors.ErrKeyExists}, + expected: []interface{}{"OK", diceerrors.ErrKeyExists.Error()}, }, { name: "BF.INFO after multiple additions", diff --git a/integration_tests/commands/resp/bloom_test.go b/integration_tests/commands/resp/bloom_test.go index e01c0b091..5af5b3044 100644 --- a/integration_tests/commands/resp/bloom_test.go +++ b/integration_tests/commands/resp/bloom_test.go @@ -43,7 +43,7 @@ func TestBFReserveAddInfoExists(t *testing.T) { { name: "BF.RESERVE on existent filter returns error", cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 1000"}, - expect: []interface{}{"OK", diceerrors.ErrKeyExists}, + expect: []interface{}{"OK", diceerrors.ErrKeyExists.Error()}, delays: []time.Duration{0, 0}, cleanUp: []string{"DEL bf"}, }, @@ -136,7 +136,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { { name: "BF.INFO on a non-existent filter", cmds: []string{"BF.INFO bf"}, - expect: []interface{}{diceerrors.ErrKeyNotFound}, + expect: []interface{}{diceerrors.ErrKeyNotFound.Error()}, delays: []time.Duration{0}, cleanUp: []string{"del bf"}, }, @@ -171,7 +171,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { { name: "BF.RESERVE with duplicate filter name", cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 2000"}, - expect: []interface{}{"OK", diceerrors.ErrKeyExists}, + expect: []interface{}{"OK", diceerrors.ErrKeyExists.Error()}, delays: []time.Duration{0, 0}, cleanUp: []string{"del bf"}, }, diff --git a/integration_tests/commands/resp/jsondebug_test.go b/integration_tests/commands/resp/jsondebug_test.go index af1bda920..8ad10a9ae 100644 --- a/integration_tests/commands/resp/jsondebug_test.go +++ b/integration_tests/commands/resp/jsondebug_test.go @@ -23,7 +23,7 @@ func TestJSONDEBUG(t *testing.T) { `JSON.SET k1 $ {"a":1}`, "JSON.DEBUG MEMORY k1", }, - expected: []interface{}{"OK", int64(89)}, + expected: []interface{}{"OK", int64(72)}, }, { name: "jsondebug with a valid path", diff --git a/integration_tests/commands/websocket/bloom_test.go b/integration_tests/commands/websocket/bloom_test.go index ba250fa95..d8c9222ca 100644 --- a/integration_tests/commands/websocket/bloom_test.go +++ b/integration_tests/commands/websocket/bloom_test.go @@ -38,7 +38,7 @@ func TestBFReserveAddInfoExists(t *testing.T) { { name: "BF.RESERVE on existent filter returns error", cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 1000"}, - expect: []interface{}{"OK", diceerrors.ErrKeyExists}, + expect: []interface{}{"OK", diceerrors.ErrKeyExists.Error()}, cleanUp: []string{"DEL bf"}, }, } @@ -127,7 +127,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { { name: "BF.INFO on a non-existent filter", cmds: []string{"BF.INFO bf"}, - expect: []interface{}{diceerrors.ErrKeyNotFound}, + expect: []interface{}{diceerrors.ErrKeyNotFound.Error()}, delays: []time.Duration{0}, cleanUp: []string{"del bf"}, }, @@ -162,7 +162,7 @@ func TestBFEdgeCasesAndErrors(t *testing.T) { { name: "BF.RESERVE with duplicate filter name", cmds: []string{"BF.RESERVE bf 0.01 1000", "BF.RESERVE bf 0.01 2000"}, - expect: []interface{}{"OK", diceerrors.ErrKeyExists}, + expect: []interface{}{"OK", diceerrors.ErrKeyExists.Error()}, delays: []time.Duration{0, 0}, cleanUp: []string{"del bf"}, }, From fdbb9794ca03532ace83b62e47a9e51c6bd22576 Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Wed, 4 Dec 2024 17:05:54 +0530 Subject: [PATCH 11/25] Object Type changed and casted during RDB serialization --- internal/eval/dump_restore.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/internal/eval/dump_restore.go b/internal/eval/dump_restore.go index 5c1b39953..7049cdd2b 100644 --- a/internal/eval/dump_restore.go +++ b/internal/eval/dump_restore.go @@ -24,10 +24,12 @@ func rdbDeserialize(data []byte) (*object.Obj, error) { if err != nil { return nil, err } - objType, err := buf.ReadByte() + _oType, err := buf.ReadByte() if err != nil { return nil, err } + + objType := object.ObjectType(_oType) switch objType { case object.ObjTypeString: value, err = readString(buf) @@ -112,7 +114,7 @@ func readSet(buf *bytes.Reader) (interface{}, error) { func rdbSerialize(obj *object.Obj) ([]byte, error) { var buf bytes.Buffer buf.WriteByte(0x09) - buf.WriteByte(obj.Type) + buf.WriteByte(byte(obj.Type)) switch obj.Type { case object.ObjTypeString: str, ok := obj.Value.(string) From 0d736f63bbcd0f61115ba7f96218eb70c1b25638 Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Wed, 4 Dec 2024 17:09:10 +0530 Subject: [PATCH 12/25] Lint fixes --- internal/eval/store_eval.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index f59e8bb83..c80ad9d63 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -2877,9 +2877,8 @@ func evalBFRESERVE(args []string, store *dstore.Store) *EvalResponse { return makeEvalResult(clientio.OK) } else if bf != nil { // bloom filter already exists return makeEvalError(diceerrors.ErrKeyExists) - } else { - return makeEvalResult(clientio.OK) } + return makeEvalResult(clientio.OK) } // evalBFADD evaluates the BF.ADD command responsible for adding an element to a bloom filter. If the filter does not From 0677ffb89c684814a47b8e308d83d89bfd8e40ee Mon Sep 17 00:00:00 2001 From: Prachi <94190717+Prachi-Jamdade@users.noreply.github.com> Date: Thu, 5 Dec 2024 23:35:09 +0530 Subject: [PATCH 13/25] feat: Add a tutorial example for URL Shortner built using DiceDB (#1259) Co-authored-by: Jyotinder --- docs/astro.config.mjs | 8 +- .../{tutorials => }/realtime-leaderboard.md | 0 .../content/docs/tutorials/url-shortener.md | 215 ++++++++++++++++++ examples/url-shortener/Dockerfile | 28 +++ examples/url-shortener/compose.yaml | 17 ++ examples/url-shortener/go.mod | 41 ++++ examples/url-shortener/go.sum | 87 +++++++ examples/url-shortener/main.go | 100 ++++++++ 8 files changed, 492 insertions(+), 4 deletions(-) rename docs/src/content/docs/{tutorials => }/realtime-leaderboard.md (100%) create mode 100644 docs/src/content/docs/tutorials/url-shortener.md create mode 100644 examples/url-shortener/Dockerfile create mode 100644 examples/url-shortener/compose.yaml create mode 100644 examples/url-shortener/go.mod create mode 100644 examples/url-shortener/go.sum create mode 100644 examples/url-shortener/main.go diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index 8ec2f2762..d3b263be3 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -33,10 +33,6 @@ export default defineConfig({ label: "Get started", autogenerate: { directory: "get-started" }, }, - // { - // label: 'Tutorials', - // autogenerate: { directory: 'tutorials' } - // }, { label: "SDK", autogenerate: { directory: "sdk" }, @@ -45,6 +41,10 @@ export default defineConfig({ label: "Connection Protocols", autogenerate: { directory: "protocols" }, }, + { + label: 'Tutorials', + autogenerate: { directory: 'tutorials' } + }, { label: "Commands", autogenerate: { directory: "commands" }, diff --git a/docs/src/content/docs/tutorials/realtime-leaderboard.md b/docs/src/content/docs/realtime-leaderboard.md similarity index 100% rename from docs/src/content/docs/tutorials/realtime-leaderboard.md rename to docs/src/content/docs/realtime-leaderboard.md diff --git a/docs/src/content/docs/tutorials/url-shortener.md b/docs/src/content/docs/tutorials/url-shortener.md new file mode 100644 index 000000000..fb47fd2d6 --- /dev/null +++ b/docs/src/content/docs/tutorials/url-shortener.md @@ -0,0 +1,215 @@ +--- +title: "Building a URL Shortener" +description: "Create a simple URL Shortener using DiceDB Go SDK." +--- + +This tutorial guides you through creating a URL shortener using DiceDB, a key-value store, with Go. We’ll set up endpoints to generate short URLs and redirect them to the original URLs. + +## Prerequisites + +1. Go (version 1.18 or later): [Download Go](https://golang.org/dl/) +2. DiceDB: A DiceDB server running locally. Refer to the [DiceDB Installation Guide](get-started/installation) if you haven't set it up yet. + +## Setup + +### 1. Install and Run DiceDB +Start a DiceDB server using Docker: +```bash +docker run -d -p 7379:7379 dicedb/dicedb +``` + +This command pulls the DiceDB Docker image and runs it, exposing it on port `7379`. + +### 2. Initialize a New Go Project +Create a new directory for your project and initialize a Go module: +```bash +mkdir url-shortener +cd url-shortener +go mod init url-shortener +``` + +### 3. Install Required Packages +Install the DiceDB Go SDK and other dependencies: +```bash +go get github.com/dicedb/dicedb-go +go get github.com/gin-gonic/gin +go get github.com/google/uuid +``` + +## Understanding DiceDB Commands +We'll use the following DiceDB commands: +### `SET` Command +Stores a key-value pair in DiceDB. +- **Syntax**: `SET key value [expiration]` + - `key`: Unique identifier (e.g., short URL code) + - `value`: Data to store (e.g., serialized JSON) + - `expiration`: Optional; time-to-live in seconds (use `0` for no expiration) +### `GET` Command +Retrieves the value associated with a key. +- **Syntax**: `GET key` + - `key`: Identifier for the data to retrieve + +## Writing the Code +Create a file named `main.go` and add the following code: + +- `main.go`: + ```go + package main + + import ( + "context" + "encoding/json" + "log" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/dicedb/dicedb-go" // DiceDB Go SDK + ) + + type URL struct { + ID string `json:"id"` + LongURL string `json:"long_url"` + ShortURL string `json:"short_url"` + } + + var db *dicedb.Client + + // Initialize DiceDB connection + func init() { + db = dicedb.NewClient(&dicedb.Options{ + Addr: "localhost:7379", + }) + } + + // Creates a short URL from a given long URL + func CreateShortURL(c *gin.Context) { + var requestBody URL + if err := c.ShouldBindJSON(&requestBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + // Generate unique short ID and construct the short URL + shortID := uuid.New().String()[:8] + requestBody.ID = shortID + requestBody.ShortURL = "http://localhost:8080/" + shortID + + // Serialize URL struct to JSON and store it in DiceDB + urlData, err := json.Marshal(requestBody) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + if err := db.Set(context.Background(), shortID, urlData, 0).Err(); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + c.JSON(http.StatusCreated, gin.H{"short_url": requestBody.ShortURL}) + } + + // Redirects to the original URL based on the short URL ID + func RedirectURL(c *gin.Context) { + id := c.Param("id") + + // Retrieve stored URL data from DiceDB + urlData, err := db.Get(context.Background(), id).Result() + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "URL not found"}) + return + } + + // Deserialize JSON data back into URL struct + var url URL + if err := json.Unmarshal([]byte(urlData), &url); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to decode URL data"}) + return + } + + // Redirect user to the original long URL + c.Redirect(http.StatusFound, url.LongURL) + } + + func main() { + router := gin.Default() + + // Define endpoints for creating short URLs and redirecting + router.POST("/shorten", CreateShortURL) + router.GET("/:id", RedirectURL) + + // Start the server on port 8080 + if err := router.Run(":8080"); err != nil { + log.Fatal("Failed to start server:", err) + } + } + ``` + +## Explanation + +### 1. Initialize the DiceDB Client +We set up the DiceDB client in the `init` function: +```go +db = dicedb.NewClient(&dicedb.Options{ + Addr: "localhost:7379", +}) +``` + +### 2. Create Short URL Endpoint +- **Input Validation**: Ensures the `long_url` field is present. +- **Short ID Generation**: Uses `uuid` to create a unique 8-character ID. +- **Data Serialization**: Converts the `URL` struct to JSON. +- **Data Storage**: Saves the JSON data in DiceDB with the `Set` command. +- **Response**: Returns the generated short URL. + +### 3. Redirect to Original URL Endpoint +- **Data Retrieval**: Fetches the URL data from DiceDB using the `Get` command. +- **Data Deserialization**: Converts JSON back to the `URL` struct. +- **Redirection**: Redirects the user to the `LongURL`. + +### 4. Start the Server +The `main` function sets up the routes and starts the server on port `8080`. + +## Running the Application + +### 1. Start the Go Application +```bash +go run main.go +``` +This will start the application server on port 8080 by default, you should see output similar to +```bash +[GIN-debug] Listening and serving HTTP on :8080 +``` + +### 2. Ensure DiceDB is Running +Ensure your DiceDB server is up and running on port `7379`. + +## Testing the application + +### 1. Shorten URL: +**Using `curl`:** +```bash +curl -X POST -H "Content-Type: application/json" -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten +``` + +**Response:** +```json +{ +"short_url": "http://localhost:8080/" +} +``` + +### 2. Redirect to Original URL: +**Using `curl`:** +```bash +curl -L http://localhost:8080/abcd1234 +``` + +**Using a Browser:** +Navigate to: +``` +http://localhost:8080/abcd1234 +``` + +You should be redirected to `https://example.com`. diff --git a/examples/url-shortener/Dockerfile b/examples/url-shortener/Dockerfile new file mode 100644 index 000000000..c062275dc --- /dev/null +++ b/examples/url-shortener/Dockerfile @@ -0,0 +1,28 @@ +# Build Stage +FROM golang:1.23 AS builder + +WORKDIR /app + +# Copy go.mod and go.sum to download dependencies +COPY go.mod go.sum ./ +RUN go mod download + +# Copy application source code and build +COPY . . +RUN CGO_ENABLED=0 GOOS=linux go build -o server . + +# Runtime Stage +FROM alpine:latest + +# Install runtime dependencies +RUN apk --no-cache add ca-certificates + +# Copy the built application +WORKDIR /root/ +COPY --from=builder /app/server . + +# Expose the application port +EXPOSE 8080 + +# Start the application +CMD ["./server"] diff --git a/examples/url-shortener/compose.yaml b/examples/url-shortener/compose.yaml new file mode 100644 index 000000000..fad46cb2b --- /dev/null +++ b/examples/url-shortener/compose.yaml @@ -0,0 +1,17 @@ +services: + dicedb: + image: dicedb/dicedb:latest + ports: + - "7379:7379" + + url-shortener: + build: + context: . + dockerfile: Dockerfile + ports: + - "8000:8000" + depends_on: + - dicedb + environment: + - DICEDB_HOST=dicedb + - DICEDB_PORT=7379 diff --git a/examples/url-shortener/go.mod b/examples/url-shortener/go.mod new file mode 100644 index 000000000..1dbd9137d --- /dev/null +++ b/examples/url-shortener/go.mod @@ -0,0 +1,41 @@ +module url-shortener + +go 1.23.2 + +require github.com/gin-gonic/gin v1.10.0 + +require ( + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect +) + +require ( + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/dicedb/dicedb-go v0.0.0-20241026093718-570de4575be3 + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect + github.com/google/uuid v1.6.0 + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.7 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/examples/url-shortener/go.sum b/examples/url-shortener/go.sum new file mode 100644 index 000000000..289e93e92 --- /dev/null +++ b/examples/url-shortener/go.sum @@ -0,0 +1,87 @@ +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/dicedb/dicedb-go v0.0.0-20241026093718-570de4575be3 h1:JvnAibMNGA0vQH+T47Y/d5/POURIvfJl3fFk0GIEBkQ= +github.com/dicedb/dicedb-go v0.0.0-20241026093718-570de4575be3/go.mod h1:p7x5/3S6wBEmiRMwxavj1I1P1xsSVQS6fcSbeai5ic4= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= +github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/examples/url-shortener/main.go b/examples/url-shortener/main.go new file mode 100644 index 000000000..583eb8a02 --- /dev/null +++ b/examples/url-shortener/main.go @@ -0,0 +1,100 @@ +package main + +import ( + "context" + "encoding/json" + "os" + "fmt" + + "log" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/dicedb/dicedb-go" // DiceDB Go SDK +) + +type URL struct { + LongURL string `json:"long_url"` +} + +var db *dicedb.Client + +// Initialize DiceDB connection +func init() { + dhost := "localhost" + if val := os.Getenv("DICEDB_HOST"); val != "" { + dhost = val + } + + dport := "7379" + if val := os.Getenv("DICEDB_PORT"); val != "" { + dport = val + } + + db = dicedb.NewClient(&dicedb.Options{ + Addr: fmt.Sprintf("%s:%s", dhost, dport), + }) +} + +// Creates a short URL from a given long URL +func createShortURL(c *gin.Context) { + var requestBody URL + if err := c.ShouldBindJSON(&requestBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + // Generate unique short ID and construct the short URL + shortID := uuid.New().String()[:8] + shortURL := "http://localhost:8080/" + shortID + + // Serialize URL struct to JSON and store it in DiceDB + urlData, err := json.Marshal(requestBody) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + if err := db.Set(context.Background(), shortID, urlData, 0).Err(); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + c.JSON(http.StatusCreated, gin.H{"short_url": shortURL}) +} + +// Redirects to the original URL based on the short URL ID +func redirectURL(c *gin.Context) { + id := c.Param("id") + + // Retrieve stored URL data from DiceDB + urlData, err := db.Get(context.Background(), id).Result() + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "URL not found"}) + return + } + + // Deserialize JSON data back into URL struct + var url URL + if err := json.Unmarshal([]byte(urlData), &url); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to decode URL data"}) + return + } + + // Redirect user to the original long URL + c.Redirect(http.StatusFound, url.LongURL) +} + +func main() { + router := gin.Default() + + // Define endpoints for creating short URLs and redirecting + router.POST("/shorten", createShortURL) + router.GET("/:id", redirectURL) + + // Start the server on port 8080 + if err := router.Run(":8080"); err != nil { + log.Fatal("Failed to start server:", err) + } +} From dfe05d51cbcf89267d3ce10ed664260069885c29 Mon Sep 17 00:00:00 2001 From: Prashant Shubham Date: Mon, 9 Dec 2024 15:46:04 +0530 Subject: [PATCH 14/25] Disabled multishard cmds and test for HTTP/WS (#1363) --- .../commands/http/command_getkeys_test.go | 15 +- .../commands/http/command_rename_test.go | 4 + integration_tests/commands/http/copy_test.go | 4 + .../commands/http/dbsize_test.go | 4 + integration_tests/commands/http/json_test.go | 1 + integration_tests/commands/http/keys_test.go | 4 + integration_tests/commands/http/mget_test.go | 4 + integration_tests/commands/http/mset_test.go | 4 + .../commands/http/object_test.go | 4 + .../commands/http/set_data_cmd_test.go | 229 +++--- integration_tests/commands/http/setup.go | 7 +- integration_tests/commands/http/touch_test.go | 4 + .../commands/resp/command_getkeys_test.go | 3 +- integration_tests/commands/websocket/setup.go | 5 +- .../commands/websocket/writeretry_test.go | 10 +- internal/eval/commands.go | 98 --- internal/eval/eval.go | 526 -------------- internal/eval/eval_test.go | 133 +--- internal/eval/store_eval.go | 135 +++- internal/iothread/cmd_meta.go | 16 + internal/server/cmd_meta.go | 652 ------------------ internal/server/{utils => httpws}/httpResp.go | 2 +- internal/server/{ => httpws}/httpServer.go | 64 +- .../{utils => httpws}/redisCmdAdapter.go | 9 +- .../{utils => httpws}/redisCmdAdapter_test.go | 2 +- .../server/{ => httpws}/websocketServer.go | 16 +- main.go | 7 +- 27 files changed, 380 insertions(+), 1582 deletions(-) delete mode 100644 internal/server/cmd_meta.go rename internal/server/{utils => httpws}/httpResp.go (92%) rename internal/server/{ => httpws}/httpServer.go (88%) rename internal/server/{utils => httpws}/redisCmdAdapter.go (97%) rename internal/server/{utils => httpws}/redisCmdAdapter_test.go (99%) rename internal/server/{ => httpws}/websocketServer.go (96%) diff --git a/integration_tests/commands/http/command_getkeys_test.go b/integration_tests/commands/http/command_getkeys_test.go index 906117296..3ebb1074a 100644 --- a/integration_tests/commands/http/command_getkeys_test.go +++ b/integration_tests/commands/http/command_getkeys_test.go @@ -38,13 +38,14 @@ func TestCommandGetKeys(t *testing.T) { }, expected: []interface{}{[]interface{}{"1 2 3 4 5 6 7"}}, }, - { - name: "MSET command", - commands: []HTTPCommand{ - {Command: "COMMAND/GETKEYS", Body: map[string]interface{}{"key": "MSET", "keys": []interface{}{"key1 key2"}, "values": []interface{}{" val1 val2"}}}, - }, - expected: []interface{}{[]interface{}{"key1 key2"}}, - }, + // Skipping these tests until multishards cmds supported by http + //{ + // name: "MSET command", + // commands: []HTTPCommand{ + // {Command: "COMMAND/GETKEYS", Body: map[string]interface{}{"key": "MSET", "keys": []interface{}{"key1 key2"}, "values": []interface{}{" val1 val2"}}}, + // }, + // expected: []interface{}{"ERR invalid command specified"}, + //}, { name: "Expire command", commands: []HTTPCommand{ diff --git a/integration_tests/commands/http/command_rename_test.go b/integration_tests/commands/http/command_rename_test.go index caef9ed8c..0c9845060 100644 --- a/integration_tests/commands/http/command_rename_test.go +++ b/integration_tests/commands/http/command_rename_test.go @@ -1,3 +1,7 @@ +//go:build ignore +// +build ignore + +// Ignored as multishard commands not supported by HTTP package http import ( diff --git a/integration_tests/commands/http/copy_test.go b/integration_tests/commands/http/copy_test.go index 51fdaa41a..fc46da0ce 100644 --- a/integration_tests/commands/http/copy_test.go +++ b/integration_tests/commands/http/copy_test.go @@ -1,3 +1,7 @@ +//go:build ignore +// +build ignore + +// Ignored as multishard commands not supported by HTTP package http import ( diff --git a/integration_tests/commands/http/dbsize_test.go b/integration_tests/commands/http/dbsize_test.go index a76929d66..430abab5e 100644 --- a/integration_tests/commands/http/dbsize_test.go +++ b/integration_tests/commands/http/dbsize_test.go @@ -1,3 +1,7 @@ +//go:build ignore +// +build ignore + +// Ignored as multishard commands not supported by HTTP package http import ( diff --git a/integration_tests/commands/http/json_test.go b/integration_tests/commands/http/json_test.go index 8a3b862ec..ebcee8c07 100644 --- a/integration_tests/commands/http/json_test.go +++ b/integration_tests/commands/http/json_test.go @@ -881,6 +881,7 @@ func TestJsonStrlen(t *testing.T) { } func TestJSONMGET(t *testing.T) { + t.Skip("Skipping this test until multishards cmds supported by http") exec := NewHTTPCommandExecutor() setupData := map[string]string{ "xx": `["hehhhe","hello"]`, diff --git a/integration_tests/commands/http/keys_test.go b/integration_tests/commands/http/keys_test.go index 75c9b05b1..6219a3945 100644 --- a/integration_tests/commands/http/keys_test.go +++ b/integration_tests/commands/http/keys_test.go @@ -1,3 +1,7 @@ +//go:build ignore +// +build ignore + +// Ignored as multishard commands not supported by HTTP package http import ( diff --git a/integration_tests/commands/http/mget_test.go b/integration_tests/commands/http/mget_test.go index 93c97e0a7..ae85f68ff 100644 --- a/integration_tests/commands/http/mget_test.go +++ b/integration_tests/commands/http/mget_test.go @@ -1,3 +1,7 @@ +//go:build ignore +// +build ignore + +// Ignored as multishard commands not supported by HTTP package http import ( diff --git a/integration_tests/commands/http/mset_test.go b/integration_tests/commands/http/mset_test.go index 8b8182e1f..7a0d47f87 100644 --- a/integration_tests/commands/http/mset_test.go +++ b/integration_tests/commands/http/mset_test.go @@ -1,3 +1,7 @@ +//go:build ignore +// +build ignore + +// Ignored as multishard commands not supported by HTTP package http import ( diff --git a/integration_tests/commands/http/object_test.go b/integration_tests/commands/http/object_test.go index e16cdab27..b0b105883 100644 --- a/integration_tests/commands/http/object_test.go +++ b/integration_tests/commands/http/object_test.go @@ -1,3 +1,7 @@ +//go:build ignore +// +build ignore + +// Ignored as multishard commands not supported by HTTP package http import ( diff --git a/integration_tests/commands/http/set_data_cmd_test.go b/integration_tests/commands/http/set_data_cmd_test.go index e850a7569..adbd66bce 100644 --- a/integration_tests/commands/http/set_data_cmd_test.go +++ b/integration_tests/commands/http/set_data_cmd_test.go @@ -159,120 +159,121 @@ func TestSetDataCmd(t *testing.T) { assert_type: []string{"equal", "array", "equal", "array"}, expected: []interface{}{float64(3), []any{string("bar"), string("baz"), string("bax")}, float64(0), []any{string("bar"), string("baz"), string("bax")}}, }, - { - name: "SADD & SDIFF", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo2", "value": "baz"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo2", "value": "bax"}}, - {Command: "SDIFF", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, - }, - assert_type: []string{"equal", "equal", "equal", "equal", "array"}, - expected: []interface{}{float64(1), float64(1), float64(1), float64(1), []any{string("bar")}}, - }, - { - name: "SADD & SDIFF with non-existing subsequent key", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SDIFF", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, - }, - assert_type: []string{"equal", "equal", "array"}, - expected: []interface{}{float64(1), float64(1), []any{string("bar"), string("baz")}}, - }, - { - name: "SADD & SDIFF with wrong key type", - commands: []HTTPCommand{ - {Command: "SET", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SDIFF", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, - }, - assert_type: []string{"equal", "equal"}, - expected: []interface{}{"OK", "WRONGTYPE Operation against a key holding the wrong kind of value"}, - }, - { - name: "SADD & SDIFF with subsequent key of wrong type", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SET", Body: map[string]interface{}{"key": "foo2", "value": "bar"}}, - {Command: "SDIFF", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, - }, - assert_type: []string{"equal", "equal", "equal", "equal"}, - expected: []interface{}{float64(1), float64(1), "OK", "WRONGTYPE Operation against a key holding the wrong kind of value"}, - }, - { - name: "SADD & SDIFF with non-existing first key", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SDIFF", Body: map[string]interface{}{"key1": "foo2", "key2": "foo"}}, - }, - assert_type: []string{"equal", "equal", "array"}, - expected: []interface{}{float64(1), float64(1), []any{}}, - }, - { - name: "SADD & SDIFF with one key", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SDIFF", Body: map[string]interface{}{"key": "foo"}}, - }, - assert_type: []string{"equal", "equal", "array"}, - expected: []interface{}{float64(1), float64(1), []any{string("bar"), string("baz")}}, - }, - { - name: "SADD & SINTER", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo2", "value": "baz"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo2", "value": "bax"}}, - {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, - }, - assert_type: []string{"equal", "equal", "equal", "equal", "array"}, - expected: []interface{}{float64(1), float64(1), float64(1), float64(1), []any{string("baz")}}, - }, - { - name: "SADD & SINTER with non-existing subsequent key", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, - }, - assert_type: []string{"equal", "equal", "array"}, - expected: []interface{}{float64(1), float64(1), []any{}}, - }, - { - name: "SADD & SINTER with wrong key type", - commands: []HTTPCommand{ - {Command: "SET", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, - }, - assert_type: []string{"equal", "equal"}, - expected: []interface{}{"OK", "WRONGTYPE Operation against a key holding the wrong kind of value"}, - }, - { - name: "SADD & SINTER with subsequent key of wrong type", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SET", Body: map[string]interface{}{"key": "foo2", "value": "bar"}}, - {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, - }, - assert_type: []string{"equal", "equal", "equal", "equal"}, - expected: []interface{}{float64(1), float64(1), "OK", "WRONGTYPE Operation against a key holding the wrong kind of value"}, - }, - { - name: "SADD & SINTER with single key", - commands: []HTTPCommand{ - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, - {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, - {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo"}}}, - }, - assert_type: []string{"equal", "equal", "array"}, - expected: []interface{}{float64(1), float64(1), []any{string("bar"), string("baz")}}, - }, + // Skipping these tests until multishards cmds supported by http + //{ + // name: "SADD & SDIFF", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo2", "value": "baz"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo2", "value": "bax"}}, + // {Command: "SDIFF", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, + // }, + // assert_type: []string{"equal", "equal", "equal", "equal", "array"}, + // expected: []interface{}{float64(1), float64(1), float64(1), float64(1), []any{string("bar")}}, + //}, + //{ + // name: "SADD & SDIFF with non-existing subsequent key", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SDIFF", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, + // }, + // assert_type: []string{"equal", "equal", "array"}, + // expected: []interface{}{float64(1), float64(1), []any{string("bar"), string("baz")}}, + //}, + //{ + // name: "SADD & SDIFF with wrong key type", + // commands: []HTTPCommand{ + // {Command: "SET", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SDIFF", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, + // }, + // assert_type: []string{"equal", "equal"}, + // expected: []interface{}{"OK", "WRONGTYPE Operation against a key holding the wrong kind of value"}, + //}, + //{ + // name: "SADD & SDIFF with subsequent key of wrong type", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SET", Body: map[string]interface{}{"key": "foo2", "value": "bar"}}, + // {Command: "SDIFF", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, + // }, + // assert_type: []string{"equal", "equal", "equal", "equal"}, + // expected: []interface{}{float64(1), float64(1), "OK", "WRONGTYPE Operation against a key holding the wrong kind of value"}, + //}, + //{ + // name: "SADD & SDIFF with non-existing first key", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SDIFF", Body: map[string]interface{}{"key1": "foo2", "key2": "foo"}}, + // }, + // assert_type: []string{"equal", "equal", "array"}, + // expected: []interface{}{float64(1), float64(1), []any{}}, + //}, + //{ + // name: "SADD & SDIFF with one key", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SDIFF", Body: map[string]interface{}{"key": "foo"}}, + // }, + // assert_type: []string{"equal", "equal", "array"}, + // expected: []interface{}{float64(1), float64(1), []any{string("bar"), string("baz")}}, + //}, + //{ + // name: "SADD & SINTER", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo2", "value": "baz"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo2", "value": "bax"}}, + // {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, + // }, + // assert_type: []string{"equal", "equal", "equal", "equal", "array"}, + // expected: []interface{}{float64(1), float64(1), float64(1), float64(1), []any{string("baz")}}, + //}, + //{ + // name: "SADD & SINTER with non-existing subsequent key", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, + // }, + // assert_type: []string{"equal", "equal", "array"}, + // expected: []interface{}{float64(1), float64(1), []any{}}, + //}, + //{ + // name: "SADD & SINTER with wrong key type", + // commands: []HTTPCommand{ + // {Command: "SET", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, + // }, + // assert_type: []string{"equal", "equal"}, + // expected: []interface{}{"OK", "WRONGTYPE Operation against a key holding the wrong kind of value"}, + //}, + //{ + // name: "SADD & SINTER with subsequent key of wrong type", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SET", Body: map[string]interface{}{"key": "foo2", "value": "bar"}}, + // {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo", "foo2"}}}, + // }, + // assert_type: []string{"equal", "equal", "equal", "equal"}, + // expected: []interface{}{float64(1), float64(1), "OK", "WRONGTYPE Operation against a key holding the wrong kind of value"}, + //}, + //{ + // name: "SADD & SINTER with single key", + // commands: []HTTPCommand{ + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "bar"}}, + // {Command: "SADD", Body: map[string]interface{}{"key": "foo", "value": "baz"}}, + // {Command: "SINTER", Body: map[string]interface{}{"values": []interface{}{"foo"}}}, + // }, + // assert_type: []string{"equal", "equal", "array"}, + // expected: []interface{}{float64(1), float64(1), []any{string("bar"), string("baz")}}, + //}, } defer exec.FireCommand(HTTPCommand{ diff --git a/integration_tests/commands/http/setup.go b/integration_tests/commands/http/setup.go index d27c67fbd..24ef1aa00 100644 --- a/integration_tests/commands/http/setup.go +++ b/integration_tests/commands/http/setup.go @@ -12,12 +12,11 @@ import ( "sync" "time" - "github.com/dicedb/dice/internal/server/utils" + "github.com/dicedb/dice/internal/server/httpws" "github.com/dicedb/dice/config" derrors "github.com/dicedb/dice/internal/errors" "github.com/dicedb/dice/internal/querymanager" - "github.com/dicedb/dice/internal/server" "github.com/dicedb/dice/internal/shard" dstore "github.com/dicedb/dice/internal/store" ) @@ -88,7 +87,7 @@ func (e *HTTPCommandExecutor) FireCommand(cmd HTTPCommand) (interface{}, error) defer resp.Body.Close() if cmd.Command != "Q.WATCH" { - var result utils.HTTPResponse + var result httpws.HTTPResponse err = json.NewDecoder(resp.Body).Decode(&result) if err != nil { return nil, err @@ -119,7 +118,7 @@ func RunHTTPServer(ctx context.Context, wg *sync.WaitGroup, opt TestServerOption queryWatcherLocal := querymanager.NewQueryManager() config.DiceConfig.HTTP.Port = opt.Port // Initialize the HTTPServer - testServer := server.NewHTTPServer(shardManager, nil) + testServer := httpws.NewHTTPServer(shardManager, nil) // Inform the user that the server is starting fmt.Println("Starting the test server on port", config.DiceConfig.HTTP.Port) shardManagerCtx, cancelShardManager := context.WithCancel(ctx) diff --git a/integration_tests/commands/http/touch_test.go b/integration_tests/commands/http/touch_test.go index 88400e51c..454a24821 100644 --- a/integration_tests/commands/http/touch_test.go +++ b/integration_tests/commands/http/touch_test.go @@ -1,3 +1,7 @@ +//go:build ignore +// +build ignore + +// Ignored as multishard commands not supported by HTTP package http import ( diff --git a/integration_tests/commands/resp/command_getkeys_test.go b/integration_tests/commands/resp/command_getkeys_test.go index 607bba994..166079b4b 100644 --- a/integration_tests/commands/resp/command_getkeys_test.go +++ b/integration_tests/commands/resp/command_getkeys_test.go @@ -15,7 +15,8 @@ var getKeysTestCases = []struct { {"Get command", "get key", []interface{}{"key"}}, {"TTL command", "ttl key", []interface{}{"key"}}, {"Del command", "del 1 2 3 4 5 6", []interface{}{"1", "2", "3", "4", "5", "6"}}, - {"MSET command", "MSET key1 val1 key2 val2", []interface{}{"key1", "key2"}}, + // TODO: Fix this for multi shard support + //{"MSET command", "MSET key1 val1 key2 val2", []interface{}{"key1", "key2"}}, {"Expire command", "expire key time extra", []interface{}{"key"}}, {"Ping command", "ping", "ERR the command has no key arguments"}, {"Invalid Get command", "get", "ERR invalid number of arguments specified for command"}, diff --git a/integration_tests/commands/websocket/setup.go b/integration_tests/commands/websocket/setup.go index cbfcc286a..281836f30 100644 --- a/integration_tests/commands/websocket/setup.go +++ b/integration_tests/commands/websocket/setup.go @@ -11,10 +11,11 @@ import ( "sync" "time" + "github.com/dicedb/dice/internal/server/httpws" + "github.com/dicedb/dice/config" derrors "github.com/dicedb/dice/internal/errors" "github.com/dicedb/dice/internal/querymanager" - "github.com/dicedb/dice/internal/server" "github.com/dicedb/dice/internal/shard" dstore "github.com/dicedb/dice/internal/store" "github.com/gorilla/websocket" @@ -117,7 +118,7 @@ func RunWebsocketServer(ctx context.Context, wg *sync.WaitGroup, opt TestServerO shardManager := shard.NewShardManager(1, watchChan, nil, globalErrChannel) queryWatcherLocal := querymanager.NewQueryManager() config.DiceConfig.WebSocket.Port = opt.Port - testServer := server.NewWebSocketServer(shardManager, testPort1, nil) + testServer := httpws.NewWebSocketServer(shardManager, testPort1, nil) shardManagerCtx, cancelShardManager := context.WithCancel(ctx) // run shard manager diff --git a/integration_tests/commands/websocket/writeretry_test.go b/integration_tests/commands/websocket/writeretry_test.go index 19555ed10..978b836af 100644 --- a/integration_tests/commands/websocket/writeretry_test.go +++ b/integration_tests/commands/websocket/writeretry_test.go @@ -2,6 +2,7 @@ package websocket import ( "fmt" + "github.com/dicedb/dice/internal/server/httpws" "net" "net/http" "net/url" @@ -9,7 +10,6 @@ import ( "testing" "time" - "github.com/dicedb/dice/internal/server" "github.com/gorilla/websocket" "github.com/stretchr/testify/assert" ) @@ -22,7 +22,7 @@ func TestWriteResponseWithRetries_Success(t *testing.T) { defer conn.Close() // Complete a write without any errors - err := server.WriteResponseWithRetries(conn, []byte("hello"), 3) + err := httpws.WriteResponseWithRetries(conn, []byte("hello"), 3) assert.NoError(t, err) } @@ -33,7 +33,7 @@ func TestWriteResponseWithRetries_NetworkError(t *testing.T) { // Simulate a network error by closing the connection beforehand conn.Close() - err := server.WriteResponseWithRetries(conn, []byte("hello"), 3) + err := httpws.WriteResponseWithRetries(conn, []byte("hello"), 3) assert.Error(t, err) assert.Contains(t, err.Error(), "network operation error") } @@ -45,7 +45,7 @@ func TestWriteResponseWithRetries_BrokenPipe(t *testing.T) { // Simulate a broken pipe error by manually triggering it. conn.UnderlyingConn().(*net.TCPConn).CloseWrite() - err := server.WriteResponseWithRetries(conn, []byte("hello"), 3) + err := httpws.WriteResponseWithRetries(conn, []byte("hello"), 3) assert.Error(t, err) assert.Contains(t, err.Error(), "broken pipe") } @@ -60,7 +60,7 @@ func TestWriteResponseWithRetries_EAGAINRetry(t *testing.T) { conn.SetWriteDeadline(time.Now().Add(1 * time.Millisecond)) for retries < 2 { - err := server.WriteResponseWithRetries(conn, []byte("hello"), 3) + err := httpws.WriteResponseWithRetries(conn, []byte("hello"), 3) if err != nil { // Retry and reset deadline after a failed attempt. conn.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)) diff --git a/internal/eval/commands.go b/internal/eval/commands.go index 787bca20c..8b2d94bb7 100644 --- a/internal/eval/commands.go +++ b/internal/eval/commands.go @@ -111,55 +111,6 @@ var ( // their implementation for HTTP and WebSocket protocols is still pending. // As a result, their Eval functions remained intact. var ( - msetCmdMeta = DiceCmdMeta{ - Name: "MSET", - Info: `MSET sets multiple keys to multiple values in the db - args should contain an even number of elements - each pair of elements will be treated as pair - Returns encoded error response if the number of arguments is not even - Returns encoded OK RESP once all entries are added`, - Eval: evalMSET, - Arity: -3, - KeySpecs: KeySpecs{BeginIndex: 1, Step: 2, LastKey: -1}, - } - - jsonMGetCmdMeta = DiceCmdMeta{ - Name: "JSON.MGET", - Info: `JSON.MGET key..key [path] - Returns the encoded RESP value of the key, if present - Null reply: If the key doesn't exist or has expired. - Error reply: If the number of arguments is incorrect or the stored value is not a JSON type.`, - Eval: evalJSONMGET, - Arity: 2, - KeySpecs: KeySpecs{BeginIndex: 1}, - } - - keysCmdMeta = DiceCmdMeta{ - Name: "KEYS", - Info: "KEYS command is used to get all the keys in the database. Complexity is O(n) where n is the number of keys in the database.", - Eval: evalKeys, - Arity: 1, - } - - MGetCmdMeta = DiceCmdMeta{ - Name: "MGET", - Info: `The MGET command returns an array of RESP values corresponding to the provided keys. - For each key, if the key is expired or does not exist, the response will be RespNIL; - otherwise, the response will be the RESP value of the key. - `, - Eval: evalMGET, - Arity: -2, - KeySpecs: KeySpecs{BeginIndex: 1, Step: 1, LastKey: -1}, - } - - //TODO: supports only http protocol, needs to be removed once http is migrated to multishard - copyCmdMeta = DiceCmdMeta{ - Name: "COPY", - Info: `COPY command copies the value stored at the source key to the destination key.`, - Eval: evalCOPY, - Arity: -2, - } - //TODO: supports only http protocol, needs to be removed once http is migrated to multishard objectCopyCmdMeta = DiceCmdMeta{ Name: "OBJECTCOPY", @@ -168,39 +119,6 @@ var ( IsMigrated: true, Arity: -2, } - touchCmdMeta = DiceCmdMeta{ - Name: "TOUCH", - Info: `TOUCH key1 key2 ... key_N - Alters the last access time of a key(s). - A key is ignored if it does not exist.`, - Eval: evalTOUCH, - Arity: -2, - KeySpecs: KeySpecs{BeginIndex: 1}, - } - sdiffCmdMeta = DiceCmdMeta{ - Name: "SDIFF", - Info: `SDIFF key1 [key2 ... key_N] - Returns the members of the set resulting from the difference between the first set and all the successive sets. - Non existing keys are treated as empty sets.`, - Eval: evalSDIFF, - Arity: -2, - KeySpecs: KeySpecs{BeginIndex: 1}, - } - sinterCmdMeta = DiceCmdMeta{ - Name: "SINTER", - Info: `SINTER key1 [key2 ... key_N] - Returns the members of the set resulting from the intersection of all the given sets. - Non existing keys are treated as empty sets.`, - Eval: evalSINTER, - Arity: -2, - KeySpecs: KeySpecs{BeginIndex: 1}, - } - dbSizeCmdMeta = DiceCmdMeta{ - Name: "DBSIZE", - Info: `DBSIZE Return the number of keys in the database`, - Eval: evalDBSIZE, - Arity: 1, - } ) // Single Shard command @@ -716,12 +634,6 @@ var ( IsMigrated: true, NewEval: evalEXISTS, } - renameCmdMeta = DiceCmdMeta{ - Name: "RENAME", - Info: "Renames a key and overwrites the destination", - Eval: evalRename, - Arity: 3, - } getexCmdMeta = DiceCmdMeta{ Name: "GETEX", Info: `Get the value of key and optionally set its expiration. @@ -1429,9 +1341,7 @@ func init() { DiceCmds["COMMAND|INFO"] = commandInfoCmdMeta DiceCmds["COMMAND|DOCS"] = commandDocsCmdMeta DiceCmds["COMMAND|GETKEYSANDFLAGS"] = commandGetKeysAndFlagsCmdMeta - DiceCmds["COPY"] = copyCmdMeta DiceCmds["OBJECTCOPY"] = objectCopyCmdMeta - DiceCmds["DBSIZE"] = dbSizeCmdMeta DiceCmds["DECR"] = decrCmdMeta DiceCmds["DECRBY"] = decrByCmdMeta DiceCmds["DEL"] = delCmdMeta @@ -1481,7 +1391,6 @@ func init() { DiceCmds["JSON.FORGET"] = jsonforgetCmdMeta DiceCmds["JSON.GET"] = jsongetCmdMeta DiceCmds["JSON.INGEST"] = jsoningestCmdMeta - DiceCmds["JSON.MGET"] = jsonMGetCmdMeta DiceCmds["JSON.NUMINCRBY"] = jsonnumincrbyCmdMeta DiceCmds["JSON.NUMMULTBY"] = jsonnummultbyCmdMeta DiceCmds["JSON.OBJKEYS"] = jsonobjkeysCmdMeta @@ -1491,13 +1400,10 @@ func init() { DiceCmds["JSON.STRLEN"] = jsonStrlenCmdMeta DiceCmds["JSON.TOGGLE"] = jsontoggleCmdMeta DiceCmds["JSON.TYPE"] = jsontypeCmdMeta - DiceCmds["KEYS"] = keysCmdMeta DiceCmds["LATENCY"] = latencyCmdMeta DiceCmds["LLEN"] = llenCmdMeta DiceCmds["LPOP"] = lpopCmdMeta DiceCmds["LPUSH"] = lpushCmdMeta - DiceCmds["MGET"] = MGetCmdMeta - DiceCmds["MSET"] = msetCmdMeta DiceCmds["OBJECT"] = objectCmdMeta DiceCmds["PERSIST"] = persistCmdMeta DiceCmds["PFADD"] = pfAddCmdMeta @@ -1505,21 +1411,17 @@ func init() { DiceCmds["PFMERGE"] = pfMergeCmdMeta DiceCmds["PING"] = pingCmdMeta DiceCmds["PTTL"] = pttlCmdMeta - DiceCmds["RENAME"] = renameCmdMeta DiceCmds["RESTORE"] = restorekeyCmdMeta DiceCmds["RPOP"] = rpopCmdMeta DiceCmds["RPUSH"] = rpushCmdMeta DiceCmds["SADD"] = saddCmdMeta DiceCmds["SCARD"] = scardCmdMeta - DiceCmds["SDIFF"] = sdiffCmdMeta DiceCmds["SET"] = setCmdMeta DiceCmds["SETBIT"] = setBitCmdMeta DiceCmds["SETEX"] = setexCmdMeta - DiceCmds["SINTER"] = sinterCmdMeta DiceCmds["SLEEP"] = sleepCmdMeta DiceCmds["SMEMBERS"] = smembersCmdMeta DiceCmds["SREM"] = sremCmdMeta - DiceCmds["TOUCH"] = touchCmdMeta DiceCmds["TTL"] = ttlCmdMeta DiceCmds["TYPE"] = typeCmdMeta DiceCmds["ZADD"] = zaddCmdMeta diff --git a/internal/eval/eval.go b/internal/eval/eval.go index 0b28e079d..c571bd6a0 100644 --- a/internal/eval/eval.go +++ b/internal/eval/eval.go @@ -1,26 +1,20 @@ package eval import ( - "errors" "fmt" - "sort" "strconv" - "strings" "time" "github.com/dicedb/dice/internal/object" "github.com/dicedb/dice/internal/sql" - "github.com/bytedance/sonic" "github.com/dicedb/dice/config" "github.com/dicedb/dice/internal/clientio" "github.com/dicedb/dice/internal/comm" diceerrors "github.com/dicedb/dice/internal/errors" "github.com/dicedb/dice/internal/querymanager" - "github.com/dicedb/dice/internal/server/utils" dstore "github.com/dicedb/dice/internal/store" - "github.com/ohler55/ojg/jp" ) type exDurationState int @@ -146,213 +140,6 @@ func EvalAUTH(args []string, c *comm.Client) []byte { return clientio.RespOK } -// evalMSET puts multiple pairs in db as in the args -// MSET is atomic, so all given keys are set at once. -// args must contain key and value pairs. - -// Returns encoded error response if at least a pair is not part of args -// Returns encoded OK RESP once new entries are added -// If the key already exists then the value will be overwritten and expiry will be discarded -// TODO: Needs to be removed after http and websocket migrated to the multithreading -func evalMSET(args []string, store *dstore.Store) []byte { - if len(args) <= 1 || len(args)%2 != 0 { - return diceerrors.NewErrArity("MSET") - } - - // MSET does not have expiry support - var exDurationMs int64 = -1 - - insertMap := make(map[string]*object.Obj, len(args)/2) - for i := 0; i < len(args); i += 2 { - key, value := args[i], args[i+1] - storedValue, oType := getRawStringOrInt(value) - insertMap[key] = store.NewObj(storedValue, exDurationMs, oType) - } - - store.PutAll(insertMap) - return clientio.RespOK -} - -// evalDBSIZE returns the number of keys in the database. -// TODO: Needs to be removed after http and websocket migrated to the multithreading -func evalDBSIZE(args []string, store *dstore.Store) []byte { - if len(args) > 0 { - return diceerrors.NewErrArity("DBSIZE") - } - - // Expired keys must be explicitly deleted since the cronFrequency for cleanup is configurable. - // A longer delay may prevent timely cleanup, leading to incorrect DBSIZE results. - dstore.DeleteExpiredKeys(store) - // return the RESP encoded value - return clientio.Encode(store.GetDBSize(), false) -} - -// trimElementAndUpdateArray trim the array between the given start and stop index -// Returns trimmed array -func trimElementAndUpdateArray(arr []any, start, stop int) []any { - updatedArray := make([]any, 0) - length := len(arr) - if len(arr) == 0 { - return updatedArray - } - var startIdx, stopIdx int - - if start >= length { - return updatedArray - } - - startIdx = adjustIndex(start, arr) - stopIdx = adjustIndex(stop, arr) - - if startIdx > stopIdx { - return updatedArray - } - - updatedArray = arr[startIdx : stopIdx+1] - return updatedArray -} - -// insertElementAndUpdateArray add an element at the given index -// Returns remaining array and error -func insertElementAndUpdateArray(arr []any, index int, elements []interface{}) (updatedArray []any, err error) { - length := len(arr) - var idx int - if index >= -length && index <= length { - idx = adjustIndex(index, arr) - } else { - return nil, errors.New("index out of bounds") - } - before := arr[:idx] - after := arr[idx:] - - elements = append(elements, after...) - before = append(before, elements...) - updatedArray = append(updatedArray, before...) - return updatedArray, nil -} - -// adjustIndex will bound the array between 0 and len(arr) - 1 -// It also handles negative indexes -func adjustIndex(idx int, arr []any) int { - // if index is positive and out of bound, limit it to the last index - if idx > len(arr) { - idx = len(arr) - 1 - } - - // if index is negative, change it to equivalent positive index - if idx < 0 { - // if index is out of bound then limit it to the first index - if idx < -len(arr) { - idx = 0 - } else { - idx = len(arr) + idx - } - } - return idx -} - -// evalJSONMGET retrieves a JSON value stored for the multiple key -// args must contain at least the key and a path; -// Returns encoded error response if incorrect number of arguments -// The RESP value of the key is encoded and then returned -// TODO: Needs to be removed after http and websocket migrated to the multithreading -func evalJSONMGET(args []string, store *dstore.Store) []byte { - if len(args) < 2 { - return diceerrors.NewErrArity("JSON.MGET") - } - - var results []interface{} - - // Default path is root if not specified - argsLen := len(args) - path := args[argsLen-1] - - for i := 0; i < (argsLen - 1); i++ { - key := args[i] - result, _ := jsonMGETHelper(store, path, key) - results = append(results, result) - } - - var interfaceObj interface{} = results - return clientio.Encode(interfaceObj, false) -} - -func jsonMGETHelper(store *dstore.Store, path, key string) (result interface{}, err2 []byte) { - // Retrieve the object from the database - obj := store.Get(key) - if obj == nil { - return result, nil - } - - // Check if the object is of JSON type - if errWithMessage := object.AssertType(obj.Type, object.ObjTypeJSON); errWithMessage != nil { - return result, errWithMessage - } - - jsonData := obj.Value - - // If path is root, return the entire JSON - if path == defaultRootPath { - resultBytes, err := sonic.Marshal(jsonData) - if err != nil { - return result, diceerrors.NewErrWithMessage("could not serialize result") - } - return string(resultBytes), nil - } - - // Parse the JSONPath expression - expr, err := jp.ParseString(path) - if err != nil { - return result, diceerrors.NewErrWithMessage("invalid JSONPath") - } - - // Execute the JSONPath query - results := expr.Get(jsonData) - if len(results) == 0 { - return result, diceerrors.NewErrWithMessage(fmt.Sprintf("Path '%s' does not exist", path)) - } - - // Serialize the result - var resultBytes []byte - if len(results) == 1 { - resultBytes, err = sonic.Marshal(results[0]) - } else { - resultBytes, err = sonic.Marshal(results) - } - if err != nil { - return nil, diceerrors.NewErrWithMessage("could not serialize result") - } - return string(resultBytes), nil -} - -// ReverseSlice takes a slice of any type and returns a new slice with the elements reversed. -func ReverseSlice[T any](slice []T) []T { - reversed := make([]T, len(slice)) - for i, v := range slice { - reversed[len(slice)-1-i] = v - } - return reversed -} - -// Parses and returns the input string as an int64 or float64 -func parseFloatInt(input string) (result interface{}, err error) { - // Try to parse as an integer - if intValue, parseErr := strconv.ParseInt(input, 10, 64); parseErr == nil { - result = intValue - return - } - - // Try to parse as a float - if floatValue, parseErr := strconv.ParseFloat(input, 64); parseErr == nil { - result = floatValue - return - } - - // If neither parsing succeeds, return an error - err = errors.New("invalid input: not a valid int or float") - return -} - func evalHELLO(args []string, store *dstore.Store) []byte { if len(args) > 1 { return diceerrors.NewErrArity("HELLO") @@ -473,316 +260,3 @@ func EvalQUNWATCH(args []string, httpOp bool, client *comm.Client) []byte { return clientio.RespOK } - -// evalKeys returns the list of keys that match the pattern should be the only param in args -// TODO: Needs to be removed after http and websocket migrated to the multithreading -func evalKeys(args []string, store *dstore.Store) []byte { - if len(args) != 1 { - return diceerrors.NewErrArity("KEYS") - } - - pattern := args[0] - keys, err := store.Keys(pattern) - if err != nil { - return clientio.Encode(err, false) - } - - return clientio.Encode(keys, false) -} - -// TODO: Needs to be removed after http and websocket migrated to the multithreading -func evalRename(args []string, store *dstore.Store) []byte { - if len(args) != 2 { - return diceerrors.NewErrArity("RENAME") - } - sourceKey := args[0] - destKey := args[1] - - // if Source key does not exist, return RESP encoded nil - sourceObj := store.Get(sourceKey) - if sourceObj == nil { - return diceerrors.NewErrWithMessage(diceerrors.NoKeyErr) - } - - // if Source and Destination Keys are same return RESP encoded ok - if sourceKey == destKey { - return clientio.RespOK - } - - if ok := store.Rename(sourceKey, destKey); ok { - return clientio.RespOK - } - return clientio.RespNIL -} - -// The MGET command returns an array of RESP values corresponding to the provided keys. -// For each key, if the key is expired or does not exist, the response will be response.RespNIL; -// otherwise, the response will be the RESP value of the key. -// MGET is atomic, it retrieves all values at once -// TODO: Needs to be removed after http and websocket migrated to the multithreading -func evalMGET(args []string, store *dstore.Store) []byte { - if len(args) < 1 { - return diceerrors.NewErrArity("MGET") - } - values := store.GetAll(args) - resp := make([]interface{}, len(args)) - for i, obj := range values { - if obj == nil { - resp[i] = clientio.RespNIL - } else { - resp[i] = obj.Value - } - } - return clientio.Encode(resp, false) -} - -// TODO: Needs to be removed after http and websocket migrated to the multithreading -func evalCOPY(args []string, store *dstore.Store) []byte { - if len(args) < 2 { - return diceerrors.NewErrArity("COPY") - } - - isReplace := false - - sourceKey := args[0] - destinationKey := args[1] - sourceObj := store.Get(sourceKey) - if sourceObj == nil { - return clientio.RespZero - } - - for i := 2; i < len(args); i++ { - arg := strings.ToUpper(args[i]) - if arg == dstore.Replace { - isReplace = true - } - } - - if isReplace { - store.Del(destinationKey) - } - - destinationObj := store.Get(destinationKey) - if destinationObj != nil { - return clientio.RespZero - } - - copyObj := sourceObj.DeepCopy() - if copyObj == nil { - return clientio.RespZero - } - - exp, ok := dstore.GetExpiry(sourceObj, store) - var exDurationMs int64 = -1 - if ok { - exDurationMs = int64(exp - uint64(utils.GetCurrentTime().UnixMilli())) - } - - store.Put(destinationKey, copyObj) - - if exDurationMs > 0 { - store.SetExpiry(copyObj, exDurationMs) - } - return clientio.RespOne -} - -// TODO: Needs to be removed after http and websocket migrated to the multithreading -func evalTOUCH(args []string, store *dstore.Store) []byte { - if len(args) == 0 { - return diceerrors.NewErrArity("TOUCH") - } - - count := 0 - for _, key := range args { - if store.Get(key) != nil { - count++ - } - } - - return clientio.Encode(count, false) -} - -func evalSDIFF(args []string, store *dstore.Store) []byte { - if len(args) < 1 { - return diceerrors.NewErrArity("SDIFF") - } - - srcKey := args[0] - obj := store.Get(srcKey) - - // if the source key does not exist, return an empty response - if obj == nil { - return clientio.Encode([]string{}, false) - } - - if err := object.AssertType(obj.Type, object.ObjTypeSet); err != nil { - return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr) - } - - // Get the set object from the store. - // store the count as the number of elements in the first set - srcSet := obj.Value.(map[string]struct{}) - count := len(srcSet) - - tmpSet := make(map[string]struct{}, count) - for k := range srcSet { - tmpSet[k] = struct{}{} - } - - // we decrement the count as we find the elements in the other sets - // if the count is 0, we skip further sets but still get them from - // the store to check if they are set objects and update their last accessed time - - for _, arg := range args[1:] { - // Get the set object from the store. - obj := store.Get(arg) - - if obj == nil { - continue - } - - // If the object exists, check if it is a set object. - if err := object.AssertType(obj.Type, object.ObjTypeSet); err != nil { - return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr) - } - - // only if the count is greater than 0, we need to check the other sets - if count > 0 { - // Get the set object. - set := obj.Value.(map[string]struct{}) - - for k := range set { - if _, ok := tmpSet[k]; ok { - delete(tmpSet, k) - count-- - } - } - } - } - - if count == 0 { - return clientio.Encode([]string{}, false) - } - - // Get the members of the set. - members := make([]string, 0, len(tmpSet)) - for k := range tmpSet { - members = append(members, k) - } - return clientio.Encode(members, false) -} - -// Migrated to the new eval, but kept for http and websocket -func evalSINTER(args []string, store *dstore.Store) []byte { - if len(args) < 1 { - return diceerrors.NewErrArity("SINTER") - } - - sets := make([]map[string]struct{}, 0, len(args)) - - empty := 0 - - for _, arg := range args { - // Get the set object from the store. - obj := store.Get(arg) - - if obj == nil { - empty++ - continue - } - - // If the object exists, check if it is a set object. - if err := object.AssertType(obj.Type, object.ObjTypeSet); err != nil { - return diceerrors.NewErrWithFormattedMessage(diceerrors.WrongTypeErr) - } - - // Get the set object. - set := obj.Value.(map[string]struct{}) - sets = append(sets, set) - } - - if empty > 0 { - return clientio.Encode([]string{}, false) - } - - // sort the sets by the number of elements in the set - // we will iterate over the smallest set - // and check if the element is present in all the other sets - sort.Slice(sets, func(i, j int) bool { - return len(sets[i]) < len(sets[j]) - }) - - count := 0 - resultSet := make(map[string]struct{}, len(sets[0])) - - // init the result set with the first set - // store the number of elements in the first set in count - // we will decrement the count if we do not find the elements in the other sets - for k := range sets[0] { - resultSet[k] = struct{}{} - count++ - } - - for i := 1; i < len(sets); i++ { - if count == 0 { - break - } - for k := range resultSet { - if _, ok := sets[i][k]; !ok { - delete(resultSet, k) - count-- - } - } - } - - if count == 0 { - return clientio.Encode([]string{}, false) - } - - members := make([]string, 0, len(resultSet)) - for k := range resultSet { - members = append(members, k) - } - return clientio.Encode(members, false) -} - -// formatFloat formats float64 as string. -// Optionally appends a decimal (.0) for whole numbers, -// if b is true. -func formatFloat(f float64, b bool) string { - formatted := strconv.FormatFloat(f, 'f', -1, 64) - if b { - parts := strings.Split(formatted, ".") - if len(parts) == 1 { - formatted += ".0" - } - } - return formatted -} - -// This method executes each operation, contained in ops array, based on commands used. -func executeBitfieldOps(value *ByteArray, ops []utils.BitFieldOp) []interface{} { - overflowType := WRAP - var result []interface{} - for _, op := range ops { - switch op.Kind { - case GET: - res := value.getBits(int(op.Offset), int(op.EVal), op.EType == SIGNED) - result = append(result, res) - case SET: - prevValue := value.getBits(int(op.Offset), int(op.EVal), op.EType == SIGNED) - value.setBits(int(op.Offset), int(op.EVal), op.Value) - result = append(result, prevValue) - case INCRBY: - res, err := value.incrByBits(int(op.Offset), int(op.EVal), op.Value, overflowType, op.EType == SIGNED) - if err != nil { - result = append(result, nil) - } else { - result = append(result, res) - } - case OVERFLOW: - overflowType = op.EType - } - } - return result -} diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index f1a629a6e..41b0088df 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -43,7 +43,6 @@ func setupTest(store *dstore.Store) *dstore.Store { func TestEval(t *testing.T) { store := dstore.NewStore(nil, nil, nil) - testEvalMSET(t, store) testEvalECHO(t, store) testEvalHELLO(t, store) testEvalSET(t, store) @@ -72,7 +71,6 @@ func TestEval(t *testing.T) { testEvalEXPIRE(t, store) testEvalEXPIRETIME(t, store) testEvalEXPIREAT(t, store) - testEvalDbsize(t, store) testEvalGETSET(t, store) testEvalHSET(t, store) testEvalHMSET(t, store) @@ -132,7 +130,6 @@ func TestEval(t *testing.T) { testEvalBitFieldRO(t, store) testEvalGEOADD(t, store) testEvalGEODIST(t, store) - testEvalSINTER(t, store) testEvalJSONSTRAPPEND(t, store) testEvalINCR(t, store) testEvalINCRBY(t, store) @@ -464,19 +461,6 @@ func testEvalGETDEL(t *testing.T, store *dstore.Store) { runMigratedEvalTests(t, tests, evalGETDEL, store) } -func testEvalMSET(t *testing.T, store *dstore.Store) { - tests := map[string]evalTestCase{ - "nil value": {input: nil, output: []byte("-ERR wrong number of arguments for 'mset' command\r\n")}, - "empty array": {input: []string{}, output: []byte("-ERR wrong number of arguments for 'mset' command\r\n")}, - "one value": {input: []string{"KEY"}, output: []byte("-ERR wrong number of arguments for 'mset' command\r\n")}, - "key val pair": {input: []string{"KEY", "VAL"}, output: clientio.RespOK}, - "odd key val pair": {input: []string{"KEY", "VAL", "KEY2"}, output: []byte("-ERR wrong number of arguments for 'mset' command\r\n")}, - "even key val pair": {input: []string{"KEY", "VAL", "KEY2", "VAL2"}, output: clientio.RespOK}, - } - - runEvalTests(t, tests, evalMSET, store) -} - func testEvalGET(t *testing.T, store *dstore.Store) { tests := []evalTestCase{ { @@ -2896,54 +2880,6 @@ func testEvalPersist(t *testing.T, store *dstore.Store) { runMigratedEvalTests(t, tests, evalPERSIST, store) } -func testEvalDbsize(t *testing.T, store *dstore.Store) { - tests := map[string]evalTestCase{ - "DBSIZE command with invalid no of args": { - input: []string{"INVALID_ARG"}, - output: []byte("-ERR wrong number of arguments for 'dbsize' command\r\n"), - }, - "no key in db": { - input: nil, - output: []byte(":0\r\n"), - }, - "one key exists in db": { - setup: func() { - evalSET([]string{"key", "val"}, store) - }, - input: nil, - output: []byte(":1\r\n"), - }, - "two keys exist in db": { - setup: func() { - evalSET([]string{"key1", "val1"}, store) - evalSET([]string{"key2", "val2"}, store) - }, - input: nil, - output: []byte(":2\r\n"), - }, - "repeating keys shall result in same dbsize": { - setup: func() { - evalSET([]string{"key1", "val1"}, store) - evalSET([]string{"key2", "val2"}, store) - evalSET([]string{"key2", "val2"}, store) - }, - input: nil, - output: []byte(":2\r\n"), - }, - "deleted keys shall be reflected in dbsize": { - setup: func() { - evalSET([]string{"key1", "val1"}, store) - evalSET([]string{"key2", "val2"}, store) - evalDEL([]string{"key2"}, store) - }, - input: nil, - output: []byte(":1\r\n"), - }, - } - - runEvalTests(t, tests, evalDBSIZE, store) -} - func testEvalPFADD(t *testing.T, store *dstore.Store) { tests := map[string]evalTestCase{ "PFADD nil value": { @@ -4397,14 +4333,6 @@ func runMigratedEvalTests(t *testing.T, tests map[string]evalTestCase, evalFunc } } -func BenchmarkEvalMSET(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - store := dstore.NewStore(nil, nil, nil) - evalMSET([]string{"KEY", "VAL", "KEY2", "VAL2"}, store) - } -} - func BenchmarkEvalHSET(b *testing.B) { store := dstore.NewStore(nil, nil, nil) for i := 0; i < b.N; i++ { @@ -5512,7 +5440,7 @@ func testEvalCOMMAND(t *testing.T, store *dstore.Store) { }, }, "command getkeys with an invalid number of arguments for a command": { - input: []string{"GETKEYS", "MSET", "key1"}, + input: []string{"GETKEYS", "SET", "key1"}, migratedOutput: EvalResponse{ Result: nil, Error: diceerrors.ErrGeneral("invalid number of arguments specified for command"), @@ -6097,13 +6025,6 @@ func testEvalHSETNX(t *testing.T, store *dstore.Store) { runMigratedEvalTests(t, tests, evalHSETNX, store) } -func TestMSETConsistency(t *testing.T) { - store := dstore.NewStore(nil, nil, nil) - evalMSET([]string{"KEY", "VAL", "KEY2", "VAL2"}, store) - - assert.Equal(t, "VAL", store.Get("KEY").Value) - assert.Equal(t, "VAL2", store.Get("KEY2").Value) -} func BenchmarkEvalHINCRBY(b *testing.B) { store := dstore.NewStore(nil, nil, nil) @@ -8108,7 +8029,7 @@ func testEvalDUMP(t *testing.T, store *dstore.Store) { input: []string{"INTEGER_KEY"}, migratedOutput: EvalResponse{ Result: "CQUAAAAAAAAACv9+l81XgsShqw==", - Error: nil, + Error: nil, }, }, "dump expired key": { @@ -8326,56 +8247,6 @@ func testEvalGEODIST(t *testing.T, store *dstore.Store) { runMigratedEvalTests(t, tests, evalGEODIST, store) } -func testEvalSINTER(t *testing.T, store *dstore.Store) { - tests := map[string]evalTestCase{ - "intersection of two sets": { - setup: func() { - evalSADD([]string{"set1", "a", "b", "c"}, store) - evalSADD([]string{"set2", "c", "d", "e"}, store) - }, - input: []string{"set1", "set2"}, - output: clientio.Encode([]string{"c"}, false), - }, - "intersection of three sets": { - setup: func() { - evalSADD([]string{"set1", "a", "b", "c"}, store) - evalSADD([]string{"set2", "b", "c", "d"}, store) - evalSADD([]string{"set3", "c", "d", "e"}, store) - }, - input: []string{"set1", "set2", "set3"}, - output: clientio.Encode([]string{"c"}, false), - }, - "intersection with single set": { - setup: func() { - evalSADD([]string{"set1", "a"}, store) - }, - input: []string{"set1"}, - output: clientio.Encode([]string{"a"}, false), - }, - "intersection with a non-existent key": { - setup: func() { - evalSADD([]string{"set1", "a", "b", "c"}, store) - }, - input: []string{"set1", "nonexistent"}, - output: clientio.Encode([]string{}, false), - }, - "intersection with wrong type": { - setup: func() { - evalSADD([]string{"set1", "a", "b", "c"}, store) - store.Put("string", &object.Obj{Value: "string", Type: object.ObjTypeString}) - }, - input: []string{"set1", "string"}, - output: []byte("-WRONGTYPE Operation against a key holding the wrong kind of value\r\n"), - }, - "no arguments": { - input: []string{}, - output: diceerrors.NewErrArity("SINTER"), - }, - } - - runEvalTests(t, tests, evalSINTER, store) -} - func testEvalJSONSTRAPPEND(t *testing.T, store *dstore.Store) { tests := map[string]evalTestCase{ "append to single field": { diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index c80ad9d63..015d20b00 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -5651,7 +5651,7 @@ func evalJSONTOGGLE(args []string, store *dstore.Store) *EvalResponse { obj.Value = jsonData } - toggleResults = ReverseSlice(toggleResults) + toggleResults = reverseSlice(toggleResults) return makeEvalResult(toggleResults) } @@ -6772,3 +6772,136 @@ func evalCommandDocs(args []string) *EvalResponse { return makeEvalResult(result) } + +// This method executes each operation, contained in ops array, based on commands used. +func executeBitfieldOps(value *ByteArray, ops []utils.BitFieldOp) []interface{} { + overflowType := WRAP + var result []interface{} + for _, op := range ops { + switch op.Kind { + case GET: + res := value.getBits(int(op.Offset), int(op.EVal), op.EType == SIGNED) + result = append(result, res) + case SET: + prevValue := value.getBits(int(op.Offset), int(op.EVal), op.EType == SIGNED) + value.setBits(int(op.Offset), int(op.EVal), op.Value) + result = append(result, prevValue) + case INCRBY: + res, err := value.incrByBits(int(op.Offset), int(op.EVal), op.Value, overflowType, op.EType == SIGNED) + if err != nil { + result = append(result, nil) + } else { + result = append(result, res) + } + case OVERFLOW: + overflowType = op.EType + } + } + return result +} + +// formatFloat formats float64 as string. +// Optionally appends a decimal (.0) for whole numbers, +// if b is true. +func formatFloat(f float64, b bool) string { + formatted := strconv.FormatFloat(f, 'f', -1, 64) + if b { + parts := strings.Split(formatted, ".") + if len(parts) == 1 { + formatted += ".0" + } + } + return formatted +} + +// trimElementAndUpdateArray trim the array between the given start and stop index +// Returns trimmed array +func trimElementAndUpdateArray(arr []any, start, stop int) []any { + updatedArray := make([]any, 0) + length := len(arr) + if len(arr) == 0 { + return updatedArray + } + var startIdx, stopIdx int + + if start >= length { + return updatedArray + } + + startIdx = adjustIndex(start, arr) + stopIdx = adjustIndex(stop, arr) + + if startIdx > stopIdx { + return updatedArray + } + + updatedArray = arr[startIdx : stopIdx+1] + return updatedArray +} + +// insertElementAndUpdateArray add an element at the given index +// Returns remaining array and error +func insertElementAndUpdateArray(arr []any, index int, elements []interface{}) (updatedArray []any, err error) { + length := len(arr) + var idx int + if index >= -length && index <= length { + idx = adjustIndex(index, arr) + } else { + return nil, errors.New("index out of bounds") + } + before := arr[:idx] + after := arr[idx:] + + elements = append(elements, after...) + before = append(before, elements...) + updatedArray = append(updatedArray, before...) + return updatedArray, nil +} + +// adjustIndex will bound the array between 0 and len(arr) - 1 +// It also handles negative indexes +func adjustIndex(idx int, arr []any) int { + // if index is positive and out of bound, limit it to the last index + if idx > len(arr) { + idx = len(arr) - 1 + } + + // if index is negative, change it to equivalent positive index + if idx < 0 { + // if index is out of bound then limit it to the first index + if idx < -len(arr) { + idx = 0 + } else { + idx = len(arr) + idx + } + } + return idx +} + +// reverseSlice takes a slice of any type and returns a new slice with the elements reversed. +func reverseSlice[T any](slice []T) []T { + reversed := make([]T, len(slice)) + for i, v := range slice { + reversed[len(slice)-1-i] = v + } + return reversed +} + +// Parses and returns the input string as an int64 or float64 +func parseFloatInt(input string) (result interface{}, err error) { + // Try to parse as an integer + if intValue, parseErr := strconv.ParseInt(input, 10, 64); parseErr == nil { + result = intValue + return + } + + // Try to parse as a float + if floatValue, parseErr := strconv.ParseFloat(input, 64); parseErr == nil { + result = floatValue + return + } + + // If neither parsing succeeds, return an error + err = errors.New("invalid input: not a valid int or float") + return +} diff --git a/internal/iothread/cmd_meta.go b/internal/iothread/cmd_meta.go index bda33d29f..ce7c35b7b 100644 --- a/internal/iothread/cmd_meta.go +++ b/internal/iothread/cmd_meta.go @@ -129,10 +129,14 @@ const ( CmdGetDel = "GETDEL" CmdLrange = "LRANGE" CmdLinsert = "LINSERT" + CmdJSONArrInsert = "JSON.ARRINSERT" + CmdJSONArrTrim = "JSON.ARRTRIM" CmdJSONArrAppend = "JSON.ARRAPPEND" CmdJSONArrLen = "JSON.ARRLEN" CmdJSONArrPop = "JSON.ARRPOP" CmdJSONClear = "JSON.CLEAR" + CmdJSONSet = "JSON.SET" + CmdJSONObjKeys = "JSON.OBJKEYS" CmdJSONDel = "JSON.DEL" CmdJSONForget = "JSON.FORGET" CmdJSONGet = "JSON.GET" @@ -267,6 +271,12 @@ var CommandsMeta = map[string]CmdMeta{ CmdJSONArrAppend: { CmdType: SingleShard, }, + CmdJSONArrInsert: { + CmdType: SingleShard, + }, + CmdJSONArrTrim: { + CmdType: SingleShard, + }, CmdJSONArrLen: { CmdType: SingleShard, }, @@ -276,6 +286,12 @@ var CommandsMeta = map[string]CmdMeta{ CmdJSONClear: { CmdType: SingleShard, }, + CmdJSONSet: { + CmdType: SingleShard, + }, + CmdJSONObjKeys: { + CmdType: SingleShard, + }, CmdJSONDel: { CmdType: SingleShard, }, diff --git a/internal/server/cmd_meta.go b/internal/server/cmd_meta.go deleted file mode 100644 index fc9927d4a..000000000 --- a/internal/server/cmd_meta.go +++ /dev/null @@ -1,652 +0,0 @@ -package server - -import ( - "github.com/dicedb/dice/internal/cmd" - "github.com/dicedb/dice/internal/comm" - "github.com/dicedb/dice/internal/eval" - "github.com/dicedb/dice/internal/shard" -) - -// Type defines the type of DiceDB command based on how it interacts with shards. -// It uses an integer value to represent different command types. -type Type int - -// Enum values for Type using iota for auto-increment. -// Global commands don't interact with shards, SingleShard commands interact with one shard, -// MultiShard commands interact with multiple shards, and Custom commands require a direct client connection. -const ( - Global Type = iota // Global commands don't need to interact with shards. - SingleShard // Single-shard commands interact with only one shard. - MultiShard // MultiShard commands interact with multiple shards using scatter-gather logic. - Custom // Custom commands involve direct client communication. -) - -// CmdMeta stores metadata about DiceDB commands, including how they are processed across shards. -// Type indicates how the command should be handled, while Breakup and Gather provide logic -// for breaking up multishard commands and gathering their responses. -type CmdMeta struct { - Cmd string // Command name. - Breakup func(mgr *shard.ShardManager, DiceDBCmd *cmd.DiceDBCmd, c *comm.Client) []cmd.DiceDBCmd // Function to break up multishard commands. - Gather func(responses ...eval.EvalResponse) []byte // Function to gather responses from shards. - RespNoShards func(args []string) []byte // Function for commands that don't interact with shards. - Type // Enum indicating the command type. -} - -// CmdMetaMap is a map that associates command names with their corresponding metadata. -var ( - CmdMetaMap = map[string]CmdMeta{} - - // Metadata for global commands that don't interact with shards. - // PING is an example of global command. - pingCmdMeta = CmdMeta{ - Cmd: "PING", - Type: Global, - } - - // Metadata for single-shard commands that only interact with one shard. - // These commands don't require breakup and gather logic. - setCmdMeta = CmdMeta{ - Cmd: "SET", - Type: SingleShard, - } - expireCmdMeta = CmdMeta{ - Cmd: "EXPIRE", - Type: SingleShard, - } - expireAtCmdMeta = CmdMeta{ - Cmd: "EXPIREAT", - Type: SingleShard, - } - expireTimeCmdMeta = CmdMeta{ - Cmd: "EXPIRETIME", - Type: SingleShard, - } - getCmdMeta = CmdMeta{ - Cmd: "GET", - Type: SingleShard, - } - getsetCmdMeta = CmdMeta{ - Cmd: "GETSET", - Type: SingleShard, - } - setexCmdMeta = CmdMeta{ - Cmd: "SETEX", - Type: SingleShard, - } - saddCmdMeta = CmdMeta{ - Cmd: "SADD", - Type: SingleShard, - } - sremCmdMeta = CmdMeta{ - Cmd: "SREM", - Type: SingleShard, - } - scardCmdMeta = CmdMeta{ - Cmd: "SCARD", - Type: SingleShard, - } - smembersCmdMeta = CmdMeta{ - Cmd: "SMEMBERS", - } - - jsonArrAppendCmdMeta = CmdMeta{ - Cmd: "JSON.ARRAPPEND", - Type: SingleShard, - } - jsonArrLenCmdMeta = CmdMeta{ - Cmd: "JSON.ARRLEN", - Type: SingleShard, - } - jsonArrPopCmdMeta = CmdMeta{ - Cmd: "JSON.ARRPOP", - Type: SingleShard, - } - jsonDebugCmdMeta = CmdMeta{ - Cmd: "JSON.DEBUG", - Type: SingleShard, - } - jsonRespCmdMeta = CmdMeta{ - Cmd: "JSON.RESP", - Type: SingleShard, - } - - getrangeCmdMeta = CmdMeta{ - Cmd: "GETRANGE", - Type: SingleShard, - } - hexistsCmdMeta = CmdMeta{ - Cmd: "HEXISTS", - Type: SingleShard, - } - hkeysCmdMeta = CmdMeta{ - Cmd: "HKEYS", - Type: SingleShard, - } - - hvalsCmdMeta = CmdMeta{ - Cmd: "HVALS", - Type: SingleShard, - } - zaddCmdMeta = CmdMeta{ - Cmd: "ZADD", - Type: SingleShard, - } - zcountCmdMeta = CmdMeta{ - Cmd: "ZCOUNT", - Type: SingleShard, - } - zrangeCmdMeta = CmdMeta{ - Cmd: "ZRANGE", - Type: SingleShard, - } - appendCmdMeta = CmdMeta{ - Cmd: "APPEND", - Type: SingleShard, - } - zpopminCmdMeta = CmdMeta{ - Cmd: "ZPOPMIN", - Type: SingleShard, - } - zrankCmdMeta = CmdMeta{ - Cmd: "ZRANK", - Type: SingleShard, - } - zcardCmdMeta = CmdMeta{ - Cmd: "ZCARD", - Type: SingleShard, - } - zremCmdMeta = CmdMeta{ - Cmd: "ZREM", - Type: SingleShard, - } - pfaddCmdMeta = CmdMeta{ - Cmd: "PFADD", - Type: SingleShard, - } - pfcountCmdMeta = CmdMeta{ - Cmd: "PFCOUNT", - Type: SingleShard, - } - pfmergeCmdMeta = CmdMeta{ - Cmd: "PFMERGE", - Type: SingleShard, - } - ttlCmdMeta = CmdMeta{ - Cmd: "TTL", - Type: SingleShard, - } - pttlCmdMeta = CmdMeta{ - Cmd: "PTTL", - Type: SingleShard, - } - setbitCmdMeta = CmdMeta{ - Cmd: "SETBIT", - Type: SingleShard, - } - getbitCmdMeta = CmdMeta{ - Cmd: "GETBIT", - Type: SingleShard, - } - bitcountCmdMeta = CmdMeta{ - Cmd: "BITCOUNT", - Type: SingleShard, - } - bitfieldCmdMeta = CmdMeta{ - Cmd: "BITFIELD", - Type: SingleShard, - } - bitposCmdMeta = CmdMeta{ - Cmd: "BITPOS", - Type: SingleShard, - } - bitfieldroCmdMeta = CmdMeta{ - Cmd: "BITFIELD_RO", - Type: SingleShard, - } - delCmdMeta = CmdMeta{ - Cmd: "DEL", - Type: SingleShard, - } - existsCmdMeta = CmdMeta{ - Cmd: "EXISTS", - Type: SingleShard, - } - persistCmdMeta = CmdMeta{ - Cmd: "PERSIST", - Type: SingleShard, - } - typeCmdMeta = CmdMeta{ - Cmd: "TYPE", - Type: SingleShard, - } - - jsonclearCmdMeta = CmdMeta{ - Cmd: "JSON.CLEAR", - Type: SingleShard, - } - - jsonstrlenCmdMeta = CmdMeta{ - Cmd: "JSON.STRLEN", - Type: SingleShard, - } - - jsonobjlenCmdMeta = CmdMeta{ - Cmd: "JSON.OBJLEN", - Type: SingleShard, - } - hlenCmdMeta = CmdMeta{ - Cmd: "HLEN", - Type: SingleShard, - } - hstrlenCmdMeta = CmdMeta{ - Cmd: "HSTRLEN", - Type: SingleShard, - } - hscanCmdMeta = CmdMeta{ - Cmd: "HSCAN", - Type: SingleShard, - } - - jsonarrinsertCmdMeta = CmdMeta{ - Cmd: "JSON.ARRINSERT", - Type: SingleShard, - } - - jsonarrtrimCmdMeta = CmdMeta{ - Cmd: "JSON.ARRTRIM", - Type: SingleShard, - } - - jsonobjkeystCmdMeta = CmdMeta{ - Cmd: "JSON.OBJKEYS", - Type: SingleShard, - } - - incrCmdMeta = CmdMeta{ - Cmd: "INCR", - Type: SingleShard, - } - incrByCmdMeta = CmdMeta{ - Cmd: "INCRBY", - Type: SingleShard, - } - decrCmdMeta = CmdMeta{ - Cmd: "DECR", - Type: SingleShard, - } - decrByCmdMeta = CmdMeta{ - Cmd: "DECRBY", - Type: SingleShard, - } - incrByFloatCmdMeta = CmdMeta{ - Cmd: "INCRBYFLOAT", - Type: SingleShard, - } - hincrbyCmdMeta = CmdMeta{ - Cmd: "HINCRBY", - Type: SingleShard, - } - hincrbyfloatCmdMeta = CmdMeta{ - Cmd: "HINCRBYFLOAT", - Type: SingleShard, - } - hrandfieldCmdMeta = CmdMeta{ - Cmd: "HRANDFIELD", - Type: SingleShard, - } - zpopmaxCmdMeta = CmdMeta{ - Cmd: "ZPOPMAX", - Type: SingleShard, - } - bfaddCmdMeta = CmdMeta{ - Cmd: "BF.ADD", - Type: SingleShard, - } - bfreserveCmdMeta = CmdMeta{ - Cmd: "BF.RESERVE", - Type: SingleShard, - } - bfexistsCmdMeta = CmdMeta{ - Cmd: "BF.EXISTS", - Type: SingleShard, - } - bfinfoCmdMeta = CmdMeta{ - Cmd: "BF.INFO", - Type: SingleShard, - } - cmsInitByDimCmdMeta = CmdMeta{ - Cmd: "CMS.INITBYDIM", - Type: SingleShard, - } - cmsInitByProbCmdMeta = CmdMeta{ - Cmd: "CMS.INITBYPROB", - Type: SingleShard, - } - cmsInfoCmdMeta = CmdMeta{ - Cmd: "CMS.INFO", - Type: SingleShard, - } - cmsIncrByCmdMeta = CmdMeta{ - Cmd: "CMS.INCRBY", - Type: SingleShard, - } - cmsQueryCmdMeta = CmdMeta{ - Cmd: "CMS.QUERY", - Type: SingleShard, - } - cmsMergeCmdMeta = CmdMeta{ - Cmd: "CMS.MERGE", - Type: SingleShard, - } - getexCmdMeta = CmdMeta{ - Cmd: "GETEX", - Type: SingleShard, - } - getdelCmdMeta = CmdMeta{ - Cmd: "GETDEL", - Type: SingleShard, - } - hsetCmdMeta = CmdMeta{ - Cmd: "HSET", - Type: SingleShard, - } - hgetCmdMeta = CmdMeta{ - Cmd: "HGET", - Type: SingleShard, - } - hsetnxCmdMeta = CmdMeta{ - Cmd: "HSETNX", - Type: SingleShard, - } - hdelCmdMeta = CmdMeta{ - Cmd: "HDEL", - Type: SingleShard, - } - hmsetCmdMeta = CmdMeta{ - Cmd: "HMSET", - Type: SingleShard, - } - hmgetCmdMeta = CmdMeta{ - Cmd: "HMGET", - Type: SingleShard, - } - lrangeCmdMeta = CmdMeta{ - Cmd: "LRANGE", - Type: SingleShard, - } - linsertCmdMeta = CmdMeta{ - Cmd: "LINSERT", - Type: SingleShard, - } - lpushCmdMeta = CmdMeta{ - Cmd: "LPUSH", - Type: SingleShard, - } - rpushCmdMeta = CmdMeta{ - Cmd: "RPUSH", - Type: SingleShard, - } - lpopCmdMeta = CmdMeta{ - Cmd: "LPOP", - Type: SingleShard, - } - rpopCmdMeta = CmdMeta{ - Cmd: "RPOP", - Type: SingleShard, - } - llenCmdMeta = CmdMeta{ - Cmd: "LLEN", - Type: SingleShard, - } - jsonForgetCmdMeta = CmdMeta{ - Cmd: "JSON.FORGET", - Type: SingleShard, - } - jsonDelCmdMeta = CmdMeta{ - Cmd: "JSON.DEL", - Type: SingleShard, - } - jsonToggleCmdMeta = CmdMeta{ - Cmd: "JSON.TOGGLE", - Type: SingleShard, - } - jsonNumIncrByCmdMeta = CmdMeta{ - Cmd: "JSON.NUMINCRBY", - Type: SingleShard, - } - jsonNumMultByCmdMeta = CmdMeta{ - Cmd: "JSON.NUMMULTBY", - Type: SingleShard, - } - jsonSetCmdMeta = CmdMeta{ - Cmd: "JSON.SET", - Type: SingleShard, - } - jsonGetCmdMeta = CmdMeta{ - Cmd: "JSON.GET", - Type: SingleShard, - } - jsonTypeCmdMeta = CmdMeta{ - Cmd: "JSON.TYPE", - Type: SingleShard, - } - jsonIngestCmdMeta = CmdMeta{ - Cmd: "JSON.INGEST", - Type: SingleShard, - } - jsonArrStrAppendCmdMeta = CmdMeta{ - Cmd: "JSON.STRAPPEND", - Type: SingleShard, - } - hGetAllCmdMeta = CmdMeta{ - Cmd: "HGETALL", - Type: SingleShard, - } - dumpCmdMeta = CmdMeta{ - Cmd: "DUMP", - Type: SingleShard, - } - restoreCmdMeta = CmdMeta{ - Cmd: "RESTORE", - Type: SingleShard, - } - geoaddCmdMeta = CmdMeta{ - Cmd: "GEOADD", - Type: SingleShard, - } - geodistCmdMeta = CmdMeta{ - Cmd: "GEODIST", - Type: SingleShard, - } - clientCmdMeta = CmdMeta{ - Cmd: "CLIENT", - Type: SingleShard, - } - latencyCmdMeta = CmdMeta{ - Cmd: "LATENCY", - Type: SingleShard, - } - flushDBCmdMeta = CmdMeta{ - Cmd: "FLUSHDB", - Type: MultiShard, - } - objectCmdMeta = CmdMeta{ - Cmd: "OBJECT", - Type: SingleShard, - } - commandCmdMeta = CmdMeta{ - Cmd: "COMMAND", - Type: SingleShard, - } - CmdCommandCountMeta = CmdMeta{ - Cmd: "COMMAND|COUNT", - Type: SingleShard, - } - CmdCommandHelp = CmdMeta{ - Cmd: "COMMAND|HELP", - Type: SingleShard, - } - CmdCommandInfo = CmdMeta{ - Cmd: "COMMAND|INFO", - Type: SingleShard, - } - CmdCommandList = CmdMeta{ - Cmd: "COMMAND|LIST", - Type: SingleShard, - } - CmdCommandDocs = CmdMeta{ - Cmd: "COMMAND|DOCS", - Type: SingleShard, - } - CmdCommandGetKeys = CmdMeta{ - Cmd: "COMMAND|GETKEYS", - Type: SingleShard, - } - CmdCommandGetKeysFlags = CmdMeta{ - Cmd: "COMMAND|GETKEYSANDFLAGS", - Type: SingleShard, - } - - // Metadata for multishard commands would go here. - // These commands require both breakup and gather logic. - - // Metadata for custom commands requiring specific client-side logic would go here. -) - -// init initializes the CmdMetaMap map by associating each command name with its corresponding metadata. -func init() { - // Global commands. - CmdMetaMap["PING"] = pingCmdMeta - - // Single-shard commands. - CmdMetaMap["SET"] = setCmdMeta - CmdMetaMap["EXPIRE"] = expireCmdMeta - CmdMetaMap["EXPIREAT"] = expireAtCmdMeta - CmdMetaMap["EXPIRETIME"] = expireTimeCmdMeta - CmdMetaMap["GET"] = getCmdMeta - CmdMetaMap["GETSET"] = getsetCmdMeta - CmdMetaMap["SETEX"] = setexCmdMeta - - CmdMetaMap["SADD"] = saddCmdMeta - CmdMetaMap["SREM"] = sremCmdMeta - CmdMetaMap["SCARD"] = scardCmdMeta - CmdMetaMap["SMEMBERS"] = smembersCmdMeta - - CmdMetaMap["JSON.ARRAPPEND"] = jsonArrAppendCmdMeta - CmdMetaMap["JSON.ARRLEN"] = jsonArrLenCmdMeta - CmdMetaMap["JSON.ARRPOP"] = jsonArrPopCmdMeta - CmdMetaMap["JSON.DEBUG"] = jsonDebugCmdMeta - CmdMetaMap["JSON.RESP"] = jsonRespCmdMeta - - CmdMetaMap["GETRANGE"] = getrangeCmdMeta - CmdMetaMap["APPEND"] = appendCmdMeta - CmdMetaMap["JSON.CLEAR"] = jsonclearCmdMeta - CmdMetaMap["JSON.STRLEN"] = jsonstrlenCmdMeta - CmdMetaMap["JSON.OBJLEN"] = jsonobjlenCmdMeta - CmdMetaMap["HEXISTS"] = hexistsCmdMeta - CmdMetaMap["HKEYS"] = hkeysCmdMeta - CmdMetaMap["HVALS"] = hvalsCmdMeta - CmdMetaMap["JSON.ARRINSERT"] = jsonarrinsertCmdMeta - CmdMetaMap["JSON.ARRTRIM"] = jsonarrtrimCmdMeta - CmdMetaMap["JSON.OBJKEYS"] = jsonobjkeystCmdMeta - CmdMetaMap["ZADD"] = zaddCmdMeta - CmdMetaMap["ZCOUNT"] = zcountCmdMeta - CmdMetaMap["ZRANGE"] = zrangeCmdMeta - CmdMetaMap["ZRANK"] = zrankCmdMeta - CmdMetaMap["ZCARD"] = zcardCmdMeta - CmdMetaMap["ZREM"] = zremCmdMeta - CmdMetaMap["PFADD"] = pfaddCmdMeta - CmdMetaMap["ZPOPMIN"] = zpopminCmdMeta - CmdMetaMap["PFCOUNT"] = pfcountCmdMeta - CmdMetaMap["PFMERGE"] = pfmergeCmdMeta - CmdMetaMap["DEL"] = delCmdMeta - CmdMetaMap["EXISTS"] = existsCmdMeta - CmdMetaMap["PERSIST"] = persistCmdMeta - CmdMetaMap["TYPE"] = typeCmdMeta - CmdMetaMap["HLEN"] = hlenCmdMeta - CmdMetaMap["HSTRLEN"] = hstrlenCmdMeta - CmdMetaMap["HSCAN"] = hscanCmdMeta - CmdMetaMap["INCR"] = incrCmdMeta - CmdMetaMap["INCRBY"] = incrByCmdMeta - CmdMetaMap["INCR"] = incrCmdMeta - CmdMetaMap["DECR"] = decrCmdMeta - CmdMetaMap["DECRBY"] = decrByCmdMeta - CmdMetaMap["INCRBYFLOAT"] = incrByFloatCmdMeta - CmdMetaMap["HINCRBY"] = hincrbyCmdMeta - CmdMetaMap["HINCRBYFLOAT"] = hincrbyfloatCmdMeta - CmdMetaMap["HRANDFIELD"] = hrandfieldCmdMeta - CmdMetaMap["PFADD"] = pfaddCmdMeta - CmdMetaMap["ZPOPMIN"] = zpopminCmdMeta - CmdMetaMap["PFCOUNT"] = pfcountCmdMeta - CmdMetaMap["PFMERGE"] = pfmergeCmdMeta - CmdMetaMap["TTL"] = ttlCmdMeta - CmdMetaMap["PTTL"] = pttlCmdMeta - CmdMetaMap["HINCRBY"] = hincrbyCmdMeta - CmdMetaMap["HINCRBYFLOAT"] = hincrbyfloatCmdMeta - CmdMetaMap["HRANDFIELD"] = hrandfieldCmdMeta - CmdMetaMap["PFADD"] = pfaddCmdMeta - CmdMetaMap["PFCOUNT"] = pfcountCmdMeta - CmdMetaMap["PFMERGE"] = pfmergeCmdMeta - CmdMetaMap["HINCRBY"] = hincrbyCmdMeta - CmdMetaMap["HINCRBYFLOAT"] = hincrbyfloatCmdMeta - CmdMetaMap["HRANDFIELD"] = hrandfieldCmdMeta - CmdMetaMap["ZPOPMAX"] = zpopmaxCmdMeta - CmdMetaMap["BF.ADD"] = bfaddCmdMeta - CmdMetaMap["BF.RESERVE"] = bfreserveCmdMeta - CmdMetaMap["BF.EXISTS"] = bfexistsCmdMeta - CmdMetaMap["BF.INFO"] = bfinfoCmdMeta - CmdMetaMap["CMS.INITBYDIM"] = cmsInitByDimCmdMeta - CmdMetaMap["CMS.INITBYPROB"] = cmsInitByProbCmdMeta - CmdMetaMap["CMS.INFO"] = cmsInfoCmdMeta - CmdMetaMap["CMS.INCRBY"] = cmsIncrByCmdMeta - CmdMetaMap["CMS.QUERY"] = cmsQueryCmdMeta - CmdMetaMap["CMS.MERGE"] = cmsMergeCmdMeta - CmdMetaMap["GETEX"] = getexCmdMeta - CmdMetaMap["GETDEL"] = getdelCmdMeta - CmdMetaMap["HSET"] = hsetCmdMeta - CmdMetaMap["HGET"] = hgetCmdMeta - CmdMetaMap["HSETNX"] = hsetnxCmdMeta - CmdMetaMap["HDEL"] = hdelCmdMeta - CmdMetaMap["HMSET"] = hmsetCmdMeta - CmdMetaMap["HMGET"] = hmgetCmdMeta - CmdMetaMap["SETBIT"] = setbitCmdMeta - CmdMetaMap["GETBIT"] = getbitCmdMeta - CmdMetaMap["BITCOUNT"] = bitcountCmdMeta - CmdMetaMap["BITFIELD"] = bitfieldCmdMeta - CmdMetaMap["BITPOS"] = bitposCmdMeta - CmdMetaMap["BITFIELD_RO"] = bitfieldroCmdMeta - CmdMetaMap["LRANGE"] = lrangeCmdMeta - CmdMetaMap["LINSERT"] = linsertCmdMeta - CmdMetaMap["LPUSH"] = lpushCmdMeta - CmdMetaMap["RPUSH"] = rpushCmdMeta - CmdMetaMap["LPOP"] = lpopCmdMeta - CmdMetaMap["RPOP"] = rpopCmdMeta - CmdMetaMap["LLEN"] = llenCmdMeta - CmdMetaMap["JSON.FORGET"] = jsonForgetCmdMeta - CmdMetaMap["JSON.DEL"] = jsonDelCmdMeta - CmdMetaMap["JSON.TOGGLE"] = jsonToggleCmdMeta - CmdMetaMap["JSON.NUMINCRBY"] = jsonNumIncrByCmdMeta - CmdMetaMap["JSON.NUMMULTBY"] = jsonNumMultByCmdMeta - CmdMetaMap["JSON.SET"] = jsonSetCmdMeta - CmdMetaMap["JSON.GET"] = jsonGetCmdMeta - CmdMetaMap["JSON.TYPE"] = jsonTypeCmdMeta - CmdMetaMap["JSON.INGEST"] = jsonIngestCmdMeta - CmdMetaMap["JSON.STRAPPEND"] = jsonArrStrAppendCmdMeta - CmdMetaMap["HGETALL"] = hGetAllCmdMeta - CmdMetaMap["DUMP"] = dumpCmdMeta - CmdMetaMap["RESTORE"] = restoreCmdMeta - CmdMetaMap["GEOADD"] = geoaddCmdMeta - CmdMetaMap["GEODIST"] = geodistCmdMeta - CmdMetaMap["CLIENT"] = clientCmdMeta - CmdMetaMap["LATENCY"] = latencyCmdMeta - CmdMetaMap["FLUSHDB"] = flushDBCmdMeta - CmdMetaMap["OBJECT"] = objectCmdMeta - CmdMetaMap["COMMAND"] = commandCmdMeta - CmdMetaMap["COMMAND|COUNT"] = CmdCommandCountMeta - CmdMetaMap["COMMAND|HELP"] = CmdCommandHelp - CmdMetaMap["COMMAND|INFO"] = CmdCommandInfo - CmdMetaMap["COMMAND|LIST"] = CmdCommandList - CmdMetaMap["COMMAND|DOCS"] = CmdCommandDocs - CmdMetaMap["COMMAND|GETKEYS"] = CmdCommandGetKeys - CmdMetaMap["COMMAND|GETKEYSANDFLAGS"] = CmdCommandGetKeysFlags -} diff --git a/internal/server/utils/httpResp.go b/internal/server/httpws/httpResp.go similarity index 92% rename from internal/server/utils/httpResp.go rename to internal/server/httpws/httpResp.go index ad66ec391..10f77ee76 100644 --- a/internal/server/utils/httpResp.go +++ b/internal/server/httpws/httpResp.go @@ -1,4 +1,4 @@ -package utils +package httpws const ( HTTPStatusSuccess string = "success" diff --git a/internal/server/httpServer.go b/internal/server/httpws/httpServer.go similarity index 88% rename from internal/server/httpServer.go rename to internal/server/httpws/httpServer.go index d472dbc62..f04c42aec 100644 --- a/internal/server/httpServer.go +++ b/internal/server/httpws/httpServer.go @@ -1,4 +1,4 @@ -package server +package httpws import ( "bytes" @@ -12,6 +12,8 @@ import ( "sync" "time" + "github.com/dicedb/dice/internal/iothread" + "github.com/dicedb/dice/internal/eval" "github.com/dicedb/dice/internal/server/abstractserver" "github.com/dicedb/dice/internal/wal" @@ -22,7 +24,6 @@ import ( "github.com/dicedb/dice/internal/comm" derrors "github.com/dicedb/dice/internal/errors" "github.com/dicedb/dice/internal/ops" - "github.com/dicedb/dice/internal/server/utils" "github.com/dicedb/dice/internal/shard" ) @@ -133,16 +134,16 @@ func (s *HTTPServer) Run(ctx context.Context) error { func (s *HTTPServer) DiceHTTPHandler(writer http.ResponseWriter, request *http.Request) { // convert to REDIS cmd - diceDBCmd, err := utils.ParseHTTPRequest(request) + diceDBCmd, err := ParseHTTPRequest(request) if err != nil { - responseJSON, _ := json.Marshal(utils.HTTPResponse{Status: utils.HTTPStatusError, Data: "Invalid HTTP request format"}) - writer.Header().Set("Content-Type", "application/json") - writer.WriteHeader(http.StatusBadRequest) // Set HTTP status code to 500 - _, err = writer.Write(responseJSON) - if err != nil { - slog.Error("Error writing response", "error", err) - } - slog.Error("Error parsing HTTP request", slog.Any("error", err)) + writeErrorResponse(writer, http.StatusBadRequest, "Invalid HTTP request format", + "Error parsing HTTP request", slog.Any("error", err)) + return + } + + if iothread.CommandsMeta[diceDBCmd.Cmd].CmdType == iothread.MultiShard { + writeErrorResponse(writer, http.StatusBadRequest, "unsupported command", + "Unsupported command received", slog.String("cmd", diceDBCmd.Cmd)) return } @@ -154,14 +155,9 @@ func (s *HTTPServer) DiceHTTPHandler(writer http.ResponseWriter, request *http.R } if unimplementedCommands[diceDBCmd.Cmd] { - responseJSON, _ := json.Marshal(utils.HTTPResponse{Status: utils.HTTPStatusError, Data: fmt.Sprintf("Command %s is not implemented with HTTP", diceDBCmd.Cmd)}) - writer.Header().Set("Content-Type", "application/json") - writer.WriteHeader(http.StatusBadRequest) // Set HTTP status code to 500 - _, err = writer.Write(responseJSON) - if err != nil { - slog.Error("Error writing response", "error", err) - } - slog.Error("Command %s is not implemented", slog.String("cmd", diceDBCmd.Cmd)) + writeErrorResponse(writer, http.StatusBadRequest, + fmt.Sprintf("Command %s is not implemented with HTTP", diceDBCmd.Cmd), + "Command is not implemented", slog.String("cmd", diceDBCmd.Cmd)) return } @@ -181,7 +177,7 @@ func (s *HTTPServer) DiceHTTPHandler(writer http.ResponseWriter, request *http.R func (s *HTTPServer) DiceHTTPQwatchHandler(writer http.ResponseWriter, request *http.Request) { // convert to REDIS cmd - diceDBCmd, err := utils.ParseHTTPRequest(request) + diceDBCmd, err := ParseHTTPRequest(request) if err != nil { http.Error(writer, "Error parsing HTTP request", http.StatusBadRequest) slog.Error("Error parsing HTTP request", slog.Any("error", err)) @@ -336,19 +332,19 @@ func (s *HTTPServer) writeResponse(writer http.ResponseWriter, result *ops.Store var ( responseValue interface{} err error - httpResponse utils.HTTPResponse + httpResponse HTTPResponse isDiceErr bool ) // Check if the command is migrated, if it is we use EvalResponse values // else we use RESPParser to decode the response - _, ok := CmdMetaMap[diceDBCmd.Cmd] + _, ok := iothread.CommandsMeta[diceDBCmd.Cmd] // TODO: Remove this conditional check and if (true) condition when all commands are migrated - if !ok { + if !ok || iothread.CommandsMeta[diceDBCmd.Cmd].CmdType == iothread.Custom { responseValue, err = DecodeEvalResponse(result.EvalResponse) if err != nil { slog.Error("Error decoding response", "error", err) - httpResponse = utils.HTTPResponse{Status: utils.HTTPStatusError, Data: "Internal Server Error"} + httpResponse = HTTPResponse{Status: HTTPStatusError, Data: "Internal Server Error"} writeJSONResponse(writer, httpResponse, http.StatusInternalServerError) return } @@ -362,11 +358,11 @@ func (s *HTTPServer) writeResponse(writer http.ResponseWriter, result *ops.Store } // Create the HTTP response - httpResponse = utils.HTTPResponse{Data: ResponseParser(responseValue)} + httpResponse = HTTPResponse{Data: ResponseParser(responseValue)} if isDiceErr { - httpResponse.Status = utils.HTTPStatusError + httpResponse.Status = HTTPStatusError } else { - httpResponse.Status = utils.HTTPStatusSuccess + httpResponse.Status = HTTPStatusSuccess } // Write the response back to the client @@ -374,7 +370,7 @@ func (s *HTTPServer) writeResponse(writer http.ResponseWriter, result *ops.Store } // Helper function to write the JSON response -func writeJSONResponse(writer http.ResponseWriter, response utils.HTTPResponse, statusCode int) { +func writeJSONResponse(writer http.ResponseWriter, response HTTPResponse, statusCode int) { writer.Header().Set("Content-Type", "application/json") writer.WriteHeader(statusCode) @@ -391,6 +387,18 @@ func writeJSONResponse(writer http.ResponseWriter, response utils.HTTPResponse, } } +func writeErrorResponse(writer http.ResponseWriter, status int, message, logMessage string, logFields ...any) { + responseJSON, _ := json.Marshal(HTTPResponse{Status: HTTPStatusError, Data: message}) + writer.Header().Set("Content-Type", "application/json") + writer.WriteHeader(status) + if _, err := writer.Write(responseJSON); err != nil { + slog.Error("HTTP-WS Error writing response", "error", err) + } + if logMessage != "" { + slog.Error(logMessage, logFields...) + } +} + // ResponseParser parses the response value for both migrated and non-migrated cmds and // returns response to be rendered for HTTP/WS response func ResponseParser(responseValue interface{}) interface{} { diff --git a/internal/server/utils/redisCmdAdapter.go b/internal/server/httpws/redisCmdAdapter.go similarity index 97% rename from internal/server/utils/redisCmdAdapter.go rename to internal/server/httpws/redisCmdAdapter.go index 06e093b27..577a73e68 100644 --- a/internal/server/utils/redisCmdAdapter.go +++ b/internal/server/httpws/redisCmdAdapter.go @@ -1,17 +1,18 @@ -package utils +package httpws import ( "encoding/base64" "encoding/json" "errors" "fmt" - "io" "net/http" "regexp" "strconv" "strings" + "github.com/dicedb/dice/internal/server/utils" + "github.com/dicedb/dice/internal/cmd" diceerrors "github.com/dicedb/dice/internal/errors" ) @@ -64,7 +65,7 @@ func ParseHTTPRequest(r *http.Request) (*cmd.DiceDBCmd, error) { queryParams := r.URL.Query() keyPrefix := queryParams.Get(KeyPrefix) - if keyPrefix != "" && command == JSONIngest { + if keyPrefix != "" && command == utils.JSONIngest { args = append(args, keyPrefix) } // Step 1: Handle JSON body if present @@ -173,7 +174,7 @@ func ParseWebsocketMessage(msg []byte) (*cmd.DiceDBCmd, error) { // if key prefix is empty for JSON.INGEST command // add "" to cmdArr - if command == JSONIngest && len(cmdArr) == 2 { + if command == utils.JSONIngest && len(cmdArr) == 2 { cmdArr = append([]string{""}, cmdArr...) } diff --git a/internal/server/utils/redisCmdAdapter_test.go b/internal/server/httpws/redisCmdAdapter_test.go similarity index 99% rename from internal/server/utils/redisCmdAdapter_test.go rename to internal/server/httpws/redisCmdAdapter_test.go index c50c7cf23..091b8bbc6 100644 --- a/internal/server/utils/redisCmdAdapter_test.go +++ b/internal/server/httpws/redisCmdAdapter_test.go @@ -1,4 +1,4 @@ -package utils +package httpws import ( "net/http/httptest" diff --git a/internal/server/websocketServer.go b/internal/server/httpws/websocketServer.go similarity index 96% rename from internal/server/websocketServer.go rename to internal/server/httpws/websocketServer.go index 93148614e..bc090ff2b 100644 --- a/internal/server/websocketServer.go +++ b/internal/server/httpws/websocketServer.go @@ -1,4 +1,4 @@ -package server +package httpws import ( "bytes" @@ -14,6 +14,8 @@ import ( "syscall" "time" + "github.com/dicedb/dice/internal/iothread" + "github.com/dicedb/dice/internal/server/abstractserver" "github.com/dicedb/dice/internal/wal" @@ -23,7 +25,6 @@ import ( "github.com/dicedb/dice/internal/comm" diceerrors "github.com/dicedb/dice/internal/errors" "github.com/dicedb/dice/internal/ops" - "github.com/dicedb/dice/internal/server/utils" "github.com/dicedb/dice/internal/shard" "github.com/gorilla/websocket" "golang.org/x/exp/rand" @@ -143,7 +144,7 @@ func (s *WebsocketServer) WebsocketHandler(w http.ResponseWriter, r *http.Reques } // parse message to dice command - diceDBCmd, err := utils.ParseWebsocketMessage(msg) + diceDBCmd, err := ParseWebsocketMessage(msg) if errors.Is(err, diceerrors.ErrEmptyCommand) { continue } else if err != nil { @@ -153,6 +154,13 @@ func (s *WebsocketServer) WebsocketHandler(w http.ResponseWriter, r *http.Reques continue } + if iothread.CommandsMeta[diceDBCmd.Cmd].CmdType == iothread.MultiShard { + if err := WriteResponseWithRetries(conn, []byte("error: unsupported command"), maxRetries); err != nil { + slog.Debug(fmt.Sprintf("Error writing message: %v", err)) + } + continue + } + // TODO - on abort, close client connection instead of closing server? if diceDBCmd.Cmd == Abort { close(s.shutdownChan) @@ -271,7 +279,7 @@ func (s *WebsocketServer) processResponse(conn *websocket.Conn, diceDBCmd *cmd.D var responseValue interface{} // Check if the command is migrated, if it is we use EvalResponse values // else we use RESPParser to decode the response - _, ok := CmdMetaMap[diceDBCmd.Cmd] + _, ok := iothread.CommandsMeta[diceDBCmd.Cmd] // TODO: Remove this conditional check and if (true) condition when all commands are migrated if !ok { responseValue, err = DecodeEvalResponse(response.EvalResponse) diff --git a/main.go b/main.go index 09744ae52..0eea883a5 100644 --- a/main.go +++ b/main.go @@ -15,6 +15,8 @@ import ( "syscall" "time" + "github.com/dicedb/dice/internal/server/httpws" + "github.com/dicedb/dice/internal/cli" "github.com/dicedb/dice/internal/logger" "github.com/dicedb/dice/internal/server/abstractserver" @@ -25,7 +27,6 @@ import ( diceerrors "github.com/dicedb/dice/internal/errors" "github.com/dicedb/dice/internal/iothread" "github.com/dicedb/dice/internal/observability" - "github.com/dicedb/dice/internal/server" "github.com/dicedb/dice/internal/server/resp" "github.com/dicedb/dice/internal/shard" dstore "github.com/dicedb/dice/internal/store" @@ -140,13 +141,13 @@ func main() { go runServer(ctx, &serverWg, respServer, serverErrCh) if config.DiceConfig.HTTP.Enabled { - httpServer := server.NewHTTPServer(shardManager, wl) + httpServer := httpws.NewHTTPServer(shardManager, wl) serverWg.Add(1) go runServer(ctx, &serverWg, httpServer, serverErrCh) } if config.DiceConfig.WebSocket.Enabled { - websocketServer := server.NewWebSocketServer(shardManager, config.DiceConfig.WebSocket.Port, wl) + websocketServer := httpws.NewWebSocketServer(shardManager, config.DiceConfig.WebSocket.Port, wl) serverWg.Add(1) go runServer(ctx, &serverWg, websocketServer, serverErrCh) } From df110f61f6fbbee4e8ec8fe82c2b786ff7f49462 Mon Sep 17 00:00:00 2001 From: Ankit Dash Date: Wed, 11 Dec 2024 00:33:14 +0530 Subject: [PATCH 15/25] Add support for command GEOPOS (#1328) Co-authored-by: pshubham --- docs/src/content/docs/commands/GEOPOS.md | 58 ++++++++++++ integration_tests/commands/http/geo_test.go | 56 ++++++++++++ integration_tests/commands/resp/geo_test.go | 60 ++++++++++++ .../commands/websocket/geo_test.go | 60 ++++++++++++ internal/eval/commands.go | 9 ++ internal/eval/eval_test.go | 91 +++++++++++++++++++ internal/eval/store_eval.go | 52 +++++++++++ internal/iothread/cmd_meta.go | 4 + 8 files changed, 390 insertions(+) create mode 100644 docs/src/content/docs/commands/GEOPOS.md diff --git a/docs/src/content/docs/commands/GEOPOS.md b/docs/src/content/docs/commands/GEOPOS.md new file mode 100644 index 000000000..2d2d16ae7 --- /dev/null +++ b/docs/src/content/docs/commands/GEOPOS.md @@ -0,0 +1,58 @@ +--- +title: GEOPOS +description: The `GEOPOS` command in DiceDB is used to return the longitude, latitude to a specified key, as stored in the sorted set. +--- + +The `GEOPOS` command in DiceDB is used to return the longitude, latitude to a specified key which is stored in a sorted set. When elements are added via `GEOADD` then they are stored in 52 bit geohash hence the values returned by `GEOPOS` might have small margins of error. + +## Syntax + +```bash +GEOPOS key [member [member ...]] +``` +## Parameters +| Parameter | Description | Type | Required | +| --------- | --------------------------------------------------------------------------------- | ------ | -------- | +| key | The name of the sorted set key whose member's coordinates are to be returned | string | Yes | +| member | A unique identifier for the location. | string | Yes | +## Return Values +| Condition | Return Value | +| ------------------------------------------------------------ | ----------------------------------------------------------- | +| Coordinates exist for the specified member(s) | Returns an ordered list of coordinates (longitude, latitude) for each specified member | +| Coordinates do not exist for the specified member(s) | Returns `(nil)` for each member without coordinates +| Incorrect Argument Count |`ERR wrong number of arguments for 'geopos' command` | +| Key does not exist in the sorted set |`Error: nil` | +## Behaviour +When the GEOPOS command is issued, DiceDB performs the following steps: +1. It checks if argument count is valid or not. If not an error is thrown. +2. It checks the validity of the key. +3. If the key is invalid then an error is returned. +4. Else it checks the members provided after the key. +5. For each member it checks the coordinates of the member. +6. If the coordinates exist then it is returned in an ordered list of latitude, longitude for the particular member. +7. If the coordinates do not exist then a ``(nil)`` is returned for that member. + +## Errors +1. `Wrong number of arguments for 'GEOPOS' command` + - Error Message: (error) ERR wrong number of arguments for 'geoadd' command. + - Occurs when the command is executed with an incorrect number of arguments. +2. `Wrong key for 'GEOPOS' command` + - Error Message: Error: nil + - Occurs when the command is executed with a key that does not exist in the sorted set. + +## Example Usage + +Here are a few examples demonstrating the usage of the GEOPOS command: +### Example: Fetching the latitude, longitude of an existing member of the set +```bash +127.0.0.1:7379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" +2 +127.0.0.1:7379> GEOPOS Sicily "Palermo" +1) 1) 13.361387 +2) 38.115556 +``` +### Example: Fetching the latitude, longitude of a member not in the set +```bash +127.0.0.1:7379> GEOPOS Sicily "Agrigento" +1) (nil) +``` \ No newline at end of file diff --git a/integration_tests/commands/http/geo_test.go b/integration_tests/commands/http/geo_test.go index a8e5c6e93..2943c3fa2 100644 --- a/integration_tests/commands/http/geo_test.go +++ b/integration_tests/commands/http/geo_test.go @@ -84,3 +84,59 @@ func TestGeoDist(t *testing.T) { }) } } + +func TestGeoPos(t *testing.T) { + exec := NewHTTPCommandExecutor() + + testCases := []struct { + name string + commands []HTTPCommand + expected []interface{} + }{ + { + name: "GEOPOS for existing points", + commands: []HTTPCommand{ + {Command: "GEOADD", Body: map[string]interface{}{"key": "index", "values": []interface{}{"13.361389", "38.115556", "Palermo"}}}, + {Command: "GEOPOS", Body: map[string]interface{}{"key": "index", "values": []interface{}{"Palermo"}}}, + }, + expected: []interface{}{ + float64(1), + []interface{}{[]interface{}{float64(13.361387), float64(38.115556)}}, + }, + }, + { + name: "GEOPOS for non-existing points", + commands: []HTTPCommand{ + {Command: "GEOPOS", Body: map[string]interface{}{"key": "index", "values": []interface{}{"NonExisting"}}}, + }, + expected: []interface{}{[]interface{}{nil}}, + }, + { + name: "GEOPOS for non-existing index", + commands: []HTTPCommand{ + {Command: "GEOPOS", Body: map[string]interface{}{"key": "NonExisting", "values": []interface{}{"Palermo"}}}, + }, + expected: []interface{}{nil}, + }, + { + name: "GEOPOS for a key not used for setting geospatial values", + commands: []HTTPCommand{ + {Command: "SET", Body: map[string]interface{}{"key": "k", "value": "v"}}, + {Command: "GEOPOS", Body: map[string]interface{}{"key": "k", "values": []interface{}{"v"}}}, + }, + expected: []interface{}{ + "OK", + "WRONGTYPE Operation against a key holding the wrong kind of value", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for i, cmd := range tc.commands { + result, _ := exec.FireCommand(cmd) + assert.Equal(t, tc.expected[i], result, "Value mismatch for cmd %v", cmd) + } + }) + } +} diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index 57bd2656a..b6eefc927 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -84,3 +84,63 @@ func TestGeoDist(t *testing.T) { }) } } + +func TestGeoPos(t *testing.T) { + conn := getLocalConnection() + defer conn.Close() + + testCases := []struct { + name string + cmds []string + expect []interface{} + delays []time.Duration + }{ + { + name: "GEOPOS b/w existing points", + cmds: []string{ + "GEOADD index 13.361389 38.115556 Palermo", + "GEOPOS index Palermo", + }, + expect: []interface{}{ + int64(1), + []interface{}{[]interface{}{"13.361387", "38.115556"}}, + }, + }, + { + name: "GEOPOS for non existing points", + cmds: []string{ + "GEOPOS index NonExisting", + }, + expect: []interface{}{ + []interface{}{"(nil)"}, + }, + }, + { + name: "GEOPOS for non existing index", + cmds: []string{ + "GEOPOS NonExisting Palermo", + }, + expect: []interface{}{"(nil)"}, + }, + { + name: "GEOPOS for a key not used for setting geospatial values", + cmds: []string{ + "SET k v", + "GEOPOS k v", + }, + expect: []interface{}{ + "OK", + "WRONGTYPE Operation against a key holding the wrong kind of value", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for i, cmd := range tc.cmds { + result := FireCommand(conn, cmd) + assert.Equal(t, tc.expect[i], result, "Value mismatch for cmd %s", cmd) + } + }) + } +} diff --git a/integration_tests/commands/websocket/geo_test.go b/integration_tests/commands/websocket/geo_test.go index e2c5d240b..e7402f7de 100644 --- a/integration_tests/commands/websocket/geo_test.go +++ b/integration_tests/commands/websocket/geo_test.go @@ -85,3 +85,63 @@ func TestGeoDist(t *testing.T) { }) } } + +func TestGeoPos(t *testing.T) { + exec := NewWebsocketCommandExecutor() + conn := exec.ConnectToServer() + defer conn.Close() + + testCases := []struct { + name string + cmds []string + expect []interface{} + }{ + { + name: "GEOPOS b/w existing points", + cmds: []string{ + "GEOADD index 13.361389 38.115556 Palermo", + "GEOPOS index Palermo", + }, + expect: []interface{}{ + float64(1), + []interface{}{[]interface{}{float64(13.361387), float64(38.115556)}}, + }, + }, + { + name: "GEOPOS for non existing points", + cmds: []string{ + "GEOPOS index NonExisting", + }, + expect: []interface{}{[]interface{}{nil}}, + }, + { + name: "GEOPOS for non existing index", + cmds: []string{ + "GEOPOS NonExisting Palermo", + }, + expect: []interface{}{nil}, + }, + { + name: "GEOPOS for a key not used for setting geospatial values", + cmds: []string{ + "SET k v", + "GEOPOS k v", + }, + expect: []interface{}{ + "OK", + "WRONGTYPE Operation against a key holding the wrong kind of value", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + for i, cmd := range tc.cmds { + result, err := exec.FireCommandAndReadResponse(conn, cmd) + assert.Nil(t, err) + assert.Equal(t, tc.expect[i], result, "Value mismatch for cmd %s", cmd) + } + }) + } +} + diff --git a/internal/eval/commands.go b/internal/eval/commands.go index 8b2d94bb7..358279ade 100644 --- a/internal/eval/commands.go +++ b/internal/eval/commands.go @@ -1213,6 +1213,14 @@ var ( NewEval: evalGEODIST, KeySpecs: KeySpecs{BeginIndex: 1}, } + geoPosCmdMeta = DiceCmdMeta{ + Name: "GEOPOS", + Info: `Returns the latitude and longitude of the members identified by the particular index.`, + Arity: -3, + NewEval: evalGEOPOS, + IsMigrated: true, + KeySpecs: KeySpecs{BeginIndex: 1}, + } jsonstrappendCmdMeta = DiceCmdMeta{ Name: "JSON.STRAPPEND", Info: `JSON.STRAPPEND key [path] value @@ -1354,6 +1362,7 @@ func init() { DiceCmds["FLUSHDB"] = flushdbCmdMeta DiceCmds["GEOADD"] = geoAddCmdMeta DiceCmds["GEODIST"] = geoDistCmdMeta + DiceCmds["GEOPOS"] = geoPosCmdMeta DiceCmds["GET"] = getCmdMeta DiceCmds["GETBIT"] = getBitCmdMeta DiceCmds["GETDEL"] = getDelCmdMeta diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index 41b0088df..284f8431e 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -130,6 +130,7 @@ func TestEval(t *testing.T) { testEvalBitFieldRO(t, store) testEvalGEOADD(t, store) testEvalGEODIST(t, store) + testEvalGEOPOS(t, store) testEvalJSONSTRAPPEND(t, store) testEvalINCR(t, store) testEvalINCRBY(t, store) @@ -8247,6 +8248,96 @@ func testEvalGEODIST(t *testing.T, store *dstore.Store) { runMigratedEvalTests(t, tests, evalGEODIST, store) } +func testEvalGEOPOS(t *testing.T, store *dstore.Store) { + tests := map[string]evalTestCase{ + "GEOPOS for existing single point": { + setup: func() { + evalGEOADD([]string{"index", "13.361387", "38.115556", "Palermo"}, store) + }, + input: []string{"index", "Palermo"}, + migratedOutput: EvalResponse{ + Result: []interface{}{[]interface{}{float64(13.361387), float64(38.115556)}}, + Error: nil, + }, + }, + "GEOPOS for multiple existing points": { + setup: func() { + evalGEOADD([]string{"points", "13.361387", "38.115556", "Palermo"}, store) + evalGEOADD([]string{"points", "15.087265", "37.502668", "Catania"}, store) + }, + input: []string{"points", "Palermo", "Catania"}, + migratedOutput: EvalResponse{ + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + []interface{}{float64(15.087265), float64(37.502668)}, + }, + Error: nil, + }, + }, + "GEOPOS for a point that does not exist": { + setup: func() { + evalGEOADD([]string{"index", "13.361387", "38.115556", "Palermo"}, store) + }, + input: []string{"index", "NonExisting"}, + migratedOutput: EvalResponse{ + Result: []interface{}{nil}, + Error: nil, + }, + }, + "GEOPOS for multiple points, one existing and one non-existing": { + setup: func() { + evalGEOADD([]string{"index", "13.361387", "38.115556", "Palermo"}, store) + }, + input: []string{"index", "Palermo", "NonExisting"}, + migratedOutput: EvalResponse{ + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + nil, + }, + Error: nil, + }, + }, + "GEOPOS for empty index": { + setup: func() { + evalGEOADD([]string{"", "13.361387", "38.115556", "Palermo"}, store) + }, + input: []string{"", "Palermo"}, + migratedOutput: EvalResponse{ + Result: []interface{}{ + []interface{}{float64(13.361387), float64(38.115556)}, + }, + Error: nil, + }, + }, + "GEOPOS with no members in key": { + input: []string{"index", "Palermo"}, + migratedOutput: EvalResponse{ + Result: clientio.NIL, + Error: nil, + }, + }, + "GEOPOS with invalid number of arguments": { + input: []string{"index"}, + migratedOutput: EvalResponse{ + Result: nil, + Error: diceerrors.ErrWrongArgumentCount("GEOPOS"), + }, + }, + "GEOPOS for a key not used for setting geospatial values": { + setup: func() { + evalSET([]string{"k", "v"}, store) + }, + input: []string{"k", "v"}, + migratedOutput: EvalResponse{ + Result: nil, + Error: errors.New("WRONGTYPE Operation against a key holding the wrong kind of value"), + }, + }, + } + + runMigratedEvalTests(t, tests, evalGEOPOS, store) +} + func testEvalJSONSTRAPPEND(t *testing.T, store *dstore.Store) { tests := map[string]evalTestCase{ "append to single field": { diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 015d20b00..8583cedad 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -6222,6 +6222,58 @@ func evalGEODIST(args []string, store *dstore.Store) *EvalResponse { } } +func evalGEOPOS(args []string, store *dstore.Store) *EvalResponse { + if len(args) < 2 { + return &EvalResponse{ + Result: nil, + Error: diceerrors.ErrWrongArgumentCount("GEOPOS"), + } + } + + key := args[0] + obj := store.Get(key) + + if obj == nil { + return &EvalResponse{ + Result: clientio.NIL, + Error: nil, + } + } + + ss, err := sortedset.FromObject(obj) + + if err != nil { + return &EvalResponse{ + Result: nil, + Error: diceerrors.ErrWrongTypeOperation, + } + } + + results := make([]interface{}, len(args)-1) + + for index := 1; index < len(args); index++ { + member := args[index] + hash, ok := ss.Get(member) + + if !ok { + results[index-1] = (nil) + continue + } + + lat, lon := geo.DecodeHash(hash) + + latFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lat), 64) + lonFloat, _ := strconv.ParseFloat(fmt.Sprintf("%f", lon), 64) + + results[index-1] = []interface{}{lonFloat, latFloat} + } + + return &EvalResponse{ + Result: results, + Error: nil, + } +} + func evalTouch(args []string, store *dstore.Store) *EvalResponse { if len(args) != 1 { return makeEvalError(diceerrors.ErrWrongArgumentCount("TOUCH")) diff --git a/internal/iothread/cmd_meta.go b/internal/iothread/cmd_meta.go index ce7c35b7b..c740bae25 100644 --- a/internal/iothread/cmd_meta.go +++ b/internal/iothread/cmd_meta.go @@ -112,6 +112,7 @@ const ( CmdRestore = "RESTORE" CmdGeoAdd = "GEOADD" CmdGeoDist = "GEODIST" + CmdGeoPos = "GEOPOS" CmdClient = "CLIENT" CmdLatency = "LATENCY" CmdDel = "DEL" @@ -517,6 +518,9 @@ var CommandsMeta = map[string]CmdMeta{ CmdGeoDist: { CmdType: SingleShard, }, + CmdGeoPos: { + CmdType: SingleShard, + }, CmdClient: { CmdType: SingleShard, }, From fe75261eceea16af13f656b054d655d2a67871ce Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Wed, 11 Dec 2024 11:30:44 +0530 Subject: [PATCH 16/25] Make target for pushging binary on a remote machine --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 9e44d0bad..88b6b78ea 100644 --- a/Makefile +++ b/Makefile @@ -105,3 +105,7 @@ release: ## build and push the Docker image to Docker Hub with the latest tag an docker build --tag dicedb/dicedb:latest --tag dicedb/dicedb:$(VERSION) . docker push dicedb/dicedb:$(VERSION) docker push dicedb/dicedb:latest + +push-binary-remote: + $(MAKE) build + scp -i ${SSH_PEM_PATH} ./dicedb ubuntu@${REMOTE_HOST}:. From f2ab39475551ec142df05627ea5b1976895e7df7 Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Fri, 13 Dec 2024 15:52:59 +0530 Subject: [PATCH 17/25] Community and Team (#1370) --- LICENSE.md => LICENSE | 0 docs/astro.config.mjs | 12 +- docs/public/funding.json | 198 +++++++--------- docs/src/components/Hero.astro | 4 +- docs/src/components/Nav.astro | 13 + docs/src/components/UserSocialHandles.astro | 63 +++++ docs/src/content/config.ts | 20 ++ docs/src/content/docs/commands/DECR.md | 2 +- docs/src/content/docs/commands/EXPIRE.md | 2 +- docs/src/content/docs/commands/EXPIREAT.md | 2 +- docs/src/content/docs/commands/EXPIRETIME.md | 2 +- docs/src/content/docs/commands/GEOPOS.md | 38 ++- docs/src/content/docs/commands/HINCRBY.md | 2 +- .../src/content/docs/commands/HINCRBYFLOAT.md | 2 +- docs/src/content/docs/commands/HRANDFIELD.md | 2 +- docs/src/content/docs/commands/INCR.md | 2 +- docs/src/content/docs/commands/JSON.OBJLEN.md | 18 +- docs/src/content/docs/commands/LINSERT.md | 2 +- docs/src/content/docs/commands/LLEN.md | 2 +- docs/src/content/docs/commands/LPOP.md | 2 +- docs/src/content/docs/commands/LPUSH.md | 2 +- docs/src/content/docs/commands/LRANGE.md | 2 +- docs/src/content/docs/commands/PTTL.md | 2 +- docs/src/content/docs/commands/RPOP.md | 2 +- docs/src/content/docs/commands/RPUSH.md | 2 +- docs/src/content/docs/commands/SETEX.md | 20 +- docs/src/content/docs/commands/SMEMBERS.md | 2 +- docs/src/content/docs/commands/TTL.md | 2 +- docs/src/content/docs/commands/ZRANK.md | 2 +- .../content/docs/get-started/hello-world.mdx | 2 +- .../docs/get-started/realtime-leaderboard.mdx | 2 +- .../content/docs/tutorials/url-shortener.md | 222 ++++++++++-------- docs/src/content/team/apoorv.json | 10 + docs/src/content/team/arpit.json | 10 + docs/src/content/team/ashwin.json | 10 + docs/src/content/team/jyotinder.json | 10 + docs/src/content/team/prashant.json | 10 + docs/src/content/team/prateek.json | 10 + docs/src/content/team/soumya.json | 10 + docs/src/content/updates/2024-07-18.md | 14 ++ docs/src/content/updates/2024-08-01.md | 25 ++ docs/src/content/updates/2024-08-08.md | 47 ++++ docs/src/content/updates/2024-08-15.md | 44 ++++ docs/src/content/updates/2024-08-19.md | 29 +++ docs/src/content/updates/2024-08-22.md | 54 +++++ docs/src/content/updates/2024-08-29.md | 40 ++++ docs/src/content/updates/2024-09-05.md | 43 ++++ docs/src/content/updates/2024-09-12.md | 52 ++++ docs/src/content/updates/2024-09-19.md | 64 +++++ docs/src/content/updates/2024-09-26.md | 54 +++++ docs/src/content/updates/2024-10-03.md | 84 +++++++ docs/src/content/updates/2024-10-10.md | 80 +++++++ docs/src/content/updates/2024-10-17.md | 65 +++++ docs/src/content/updates/2024-10-24.md | 59 +++++ docs/src/content/updates/2024-11-07.md | 35 +++ docs/src/content/updates/2024-11-14.md | 29 +++ docs/src/content/updates/2024-11-21.md | 44 ++++ docs/src/content/updates/2024-11-28.md | 48 ++++ docs/src/content/updates/2024-12-05.md | 21 ++ docs/src/layouts/BlogLayout.astro | 77 +++--- docs/src/layouts/Head.astro | 1 - docs/src/pages/community/index.astro | 69 ++++++ docs/src/pages/team.astro | 122 ++++++++++ docs/src/pages/updates/[slug].astro | 20 ++ 64 files changed, 1645 insertions(+), 295 deletions(-) rename LICENSE.md => LICENSE (100%) create mode 100644 docs/src/components/UserSocialHandles.astro create mode 100644 docs/src/content/team/apoorv.json create mode 100644 docs/src/content/team/arpit.json create mode 100644 docs/src/content/team/ashwin.json create mode 100644 docs/src/content/team/jyotinder.json create mode 100644 docs/src/content/team/prashant.json create mode 100644 docs/src/content/team/prateek.json create mode 100644 docs/src/content/team/soumya.json create mode 100644 docs/src/content/updates/2024-07-18.md create mode 100644 docs/src/content/updates/2024-08-01.md create mode 100644 docs/src/content/updates/2024-08-08.md create mode 100644 docs/src/content/updates/2024-08-15.md create mode 100644 docs/src/content/updates/2024-08-19.md create mode 100644 docs/src/content/updates/2024-08-22.md create mode 100644 docs/src/content/updates/2024-08-29.md create mode 100644 docs/src/content/updates/2024-09-05.md create mode 100644 docs/src/content/updates/2024-09-12.md create mode 100644 docs/src/content/updates/2024-09-19.md create mode 100644 docs/src/content/updates/2024-09-26.md create mode 100644 docs/src/content/updates/2024-10-03.md create mode 100644 docs/src/content/updates/2024-10-10.md create mode 100644 docs/src/content/updates/2024-10-17.md create mode 100644 docs/src/content/updates/2024-10-24.md create mode 100644 docs/src/content/updates/2024-11-07.md create mode 100644 docs/src/content/updates/2024-11-14.md create mode 100644 docs/src/content/updates/2024-11-21.md create mode 100644 docs/src/content/updates/2024-11-28.md create mode 100644 docs/src/content/updates/2024-12-05.md create mode 100644 docs/src/pages/community/index.astro create mode 100644 docs/src/pages/team.astro create mode 100644 docs/src/pages/updates/[slug].astro diff --git a/LICENSE.md b/LICENSE similarity index 100% rename from LICENSE.md rename to LICENSE diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs index d3b263be3..90c9a2338 100644 --- a/docs/astro.config.mjs +++ b/docs/astro.config.mjs @@ -15,17 +15,17 @@ export default defineConfig({ // useStarlightDarkModeSwitch: false, favicon: "/favicon.png", editLink: { - baseUrl: 'https://github.com/DiceDB/dice/edit/master/docs/', + baseUrl: "https://github.com/DiceDB/dice/edit/master/docs/", }, lastUpdated: true, expressiveCode: { textMarkers: true, - themes: ['ayu-dark','light-plus'], + themes: ["ayu-dark", "light-plus"], defaultProps: { wrap: true, }, - styleOverrides: { - borderRadius: '0.2rem' + styleOverrides: { + borderRadius: "0.2rem", }, }, sidebar: [ @@ -42,8 +42,8 @@ export default defineConfig({ autogenerate: { directory: "protocols" }, }, { - label: 'Tutorials', - autogenerate: { directory: 'tutorials' } + label: "Tutorials", + autogenerate: { directory: "tutorials" }, }, { label: "Commands", diff --git a/docs/public/funding.json b/docs/public/funding.json index e26b90e43..703ed0d2f 100644 --- a/docs/public/funding.json +++ b/docs/public/funding.json @@ -1,117 +1,101 @@ { "version": "v1.0.0", "entity": { - "type": "organisation", - "role": "owner", + "type": "organisation", + "role": "owner", + "name": "DiceDB", + "email": "arpit@dicedb.io", + "phone": "", + "description": "DiceDB is a redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware.", + "webpageUrl": { + "url": "https://dicedb.io" + } + }, + "projects": [ + { + "guid": "dicedb", "name": "DiceDB", - "email": "arpit@dicedb.io", - "phone": "", "description": "DiceDB is a redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware.", "webpageUrl": { - "url": "https://dicedb.io" + "url": "https://dicedb.io" + }, + "repositoryUrl": { + "url": "https://github.com/dicedb/dice" + }, + "licenses": ["BSL"], + "tags": ["database", "high-performance", "key-value-store"] + } + ], + "funding": { + "channels": [ + { + "guid": "other", + "type": "other", + "address": "", + "description": "Yet to setup" } - }, - "projects": [ + ], + "plans": [ + { + "guid": "perf-test", + "status": "active", + "name": "Load and performance testing", + "description": "This will cover the monthly server hosting costs to run load tests, performance tests, and CI for core database engine.", + "amount": 5000, + "currency": "USD", + "frequency": "monthly", + "channels": ["other"] + }, { - "guid": "dicedb", - "name": "DiceDB", - "description": "DiceDB is a redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware.", - "webpageUrl": { - "url": "https://dicedb.io" - }, - "repositoryUrl": { - "url": "https://github.com/dicedb/dice" - }, - "licenses": [ - "BSL" - ], - "tags": [ - "database", - "high-performance", - "key-value-store" - ] + "guid": "developer-time", + "status": "active", + "name": "Developer compensation", + "description": "This will cover the cost of seven senior engineers working part-time on building DiceDB.", + "amount": 70000, + "currency": "USD", + "frequency": "monthly", + "channels": ["other"] + }, + { + "guid": "commuunity-contributors-and-events", + "status": "active", + "name": "Community swags, events and hackathons", + "description": "This will cover the cost of 160+ OSS contributors by giving them DiceDB swags and keeping their morale high. Some fraction of the funds will also be used to run hackathons and some community events like Database Paper Reading Sessions. We aim to build a thriving community around DiceDB and databases in India.", + "amount": 20000, + "currency": "USD", + "frequency": "monthly", + "channels": ["other"] + }, + { + "guid": "hosting-playground", + "status": "active", + "name": "Hosting Playground", + "description": "This will cover the monthly server hosting costs to run DiceDB and host Playground making it easier for people to try out DiceDB.", + "amount": 4000, + "currency": "USD", + "frequency": "monthly", + "channels": ["other"] + }, + { + "guid": "angel-plan", + "status": "active", + "name": "Goodwill plan", + "description": "Pay anything you wish to show your goodwill for the project.", + "amount": 1000, + "currency": "USD", + "frequency": "one-time", + "channels": ["other"] } - ], - "funding": { - "channels": [ - { - "guid": "other", - "type": "other", - "address": "", - "description": "Yet to setup" - } - ], - "plans": [ - { - "guid": "perf-test", - "status": "active", - "name": "Load and performance testing", - "description": "This will cover the monthly server hosting costs to run load tests, performance tests, and CI for core database engine.", - "amount": 5000, - "currency": "USD", - "frequency": "monthly", - "channels": [ - "other" - ] - }, - { - "guid": "developer-time", - "status": "active", - "name": "Developer compensation", - "description": "This will cover the cost of seven senior engineers working part-time on building DiceDB.", - "amount": 70000, - "currency": "USD", - "frequency": "monthly", - "channels": [ - "other" - ] - }, - { - "guid": "commuunity-contributors-and-events", - "status": "active", - "name": "Community swags, events and hackathons", - "description": "This will cover the cost of 160+ OSS contributors by giving them DiceDB swags and keeping their morale high. Some fraction of the funds will also be used to run hackathons and some community events like Database Paper Reading Sessions. We aim to build a thriving community around DiceDB and databases in India.", - "amount": 20000, - "currency": "USD", - "frequency": "monthly", - "channels": [ - "other" - ] - }, - { - "guid": "hosting-playground", - "status": "active", - "name": "Hosting Playground", - "description": "This will cover the monthly server hosting costs to run DiceDB and host Playground making it easier for people to try out DiceDB.", - "amount": 4000, - "currency": "USD", - "frequency": "monthly", - "channels": [ - "other" - ] - }, - { - "guid": "angel-plan", - "status": "active", - "name": "Goodwill plan", - "description": "Pay anything you wish to show your goodwill for the project.", - "amount": 1000, - "currency": "USD", - "frequency": "one-time", - "channels": [ - "other" - ] - } - ], - "history": [ - { - "year": 2024, - "income": 0, - "expenses": 100, - "taxes": 0, - "currency": "USD", - "description": "Infrastrucuture cost" - } - ] + ], + "history": [ + { + "year": 2024, + "income": 0, + "expenses": 100, + "taxes": 0, + "currency": "USD", + "description": "Infrastrucuture cost" + } + ] } -} \ No newline at end of file +} diff --git a/docs/src/components/Hero.astro b/docs/src/components/Hero.astro index dbe53d9b8..9dd3d46c8 100644 --- a/docs/src/components/Hero.astro +++ b/docs/src/components/Hero.astro @@ -1,7 +1,5 @@ --- -import { Github, MoveRight } from "lucide-astro"; -import Dice from "./Dice.astro"; -import site from "../data/site.json"; +import { Github } from "lucide-astro"; ---
diff --git a/docs/src/components/Nav.astro b/docs/src/components/Nav.astro index 38f5a671e..d153160f9 100644 --- a/docs/src/components/Nav.astro +++ b/docs/src/components/Nav.astro @@ -1,6 +1,7 @@ --- const pathname = new URL(Astro.request.url).pathname; const currentPage = pathname.split("/")[1]; +const currentSubPage = pathname.split("/")[2]; // To identify subpages under "community" import SocialHandlesIcons from "./SocialHandlesIcons.astro"; --- @@ -50,6 +51,18 @@ import SocialHandlesIcons from "./SocialHandlesIcons.astro"; > Blog + + Community + + + Team + diff --git a/docs/src/components/UserSocialHandles.astro b/docs/src/components/UserSocialHandles.astro new file mode 100644 index 000000000..ffc531408 --- /dev/null +++ b/docs/src/components/UserSocialHandles.astro @@ -0,0 +1,63 @@ +--- +import { Twitter, Github, Linkedin, Globe } from "lucide-astro"; +const { x, github, linkedin, website } = Astro.props; +--- + + diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts index 28a0c6e25..7713bcd56 100644 --- a/docs/src/content/config.ts +++ b/docs/src/content/config.ts @@ -31,9 +31,29 @@ const releases = defineCollection({ }), }); +const updates = defineCollection({ + type: "content", + schema: z.object({}), +}); + +const team = defineCollection({ + type: "data", + schema: z.object({ + name: z.string(), + avatar_url: z.string(), + roles: z.array(z.string()), + x: z.string(), + linkedin: z.string(), + github: z.string(), + website: z.string(), + }), +}); + export const collections = { blog, authors, releases, + team, + updates, docs: defineCollection({ schema: docsSchema() }), }; diff --git a/docs/src/content/docs/commands/DECR.md b/docs/src/content/docs/commands/DECR.md index e63ce4549..d813bf206 100644 --- a/docs/src/content/docs/commands/DECR.md +++ b/docs/src/content/docs/commands/DECR.md @@ -100,4 +100,4 @@ OK ## Alternatives -You can also use the [`DECRBY`](/commands/decrby) command to decrement the value of a key by a specified amount. \ No newline at end of file +You can also use the [`DECRBY`](/commands/decrby) command to decrement the value of a key by a specified amount. diff --git a/docs/src/content/docs/commands/EXPIRE.md b/docs/src/content/docs/commands/EXPIRE.md index f31ce0d89..fe4954a5c 100644 --- a/docs/src/content/docs/commands/EXPIRE.md +++ b/docs/src/content/docs/commands/EXPIRE.md @@ -103,4 +103,4 @@ This example shows what happens when trying to set an expiration on a non-existe ## Alternatives -- Use [`EXPIREAT`](/commands/expireat) command for more precise expiration control based on Unix timestamps \ No newline at end of file +- Use [`EXPIREAT`](/commands/expireat) command for more precise expiration control based on Unix timestamps diff --git a/docs/src/content/docs/commands/EXPIREAT.md b/docs/src/content/docs/commands/EXPIREAT.md index 933050530..582d612a6 100644 --- a/docs/src/content/docs/commands/EXPIREAT.md +++ b/docs/src/content/docs/commands/EXPIREAT.md @@ -144,4 +144,4 @@ OK ## Alternatives -- Use [`EXPIRE`](/commands/expire) command for simpler expiration control based on relative time \ No newline at end of file +- Use [`EXPIRE`](/commands/expire) command for simpler expiration control based on relative time diff --git a/docs/src/content/docs/commands/EXPIRETIME.md b/docs/src/content/docs/commands/EXPIRETIME.md index ededacc4c..e235174d5 100644 --- a/docs/src/content/docs/commands/EXPIRETIME.md +++ b/docs/src/content/docs/commands/EXPIRETIME.md @@ -76,4 +76,4 @@ In this example, the key `nonExistentKey` does not exist in the database. The `E ## Alternatives - Use [`TTL`](/commands/ttl) to get relative expiration times -- Use [`PTTL`](/commands/pttl) to get relative expiration times in milliseconds \ No newline at end of file +- Use [`PTTL`](/commands/pttl) to get relative expiration times in milliseconds diff --git a/docs/src/content/docs/commands/GEOPOS.md b/docs/src/content/docs/commands/GEOPOS.md index 2d2d16ae7..049908eb9 100644 --- a/docs/src/content/docs/commands/GEOPOS.md +++ b/docs/src/content/docs/commands/GEOPOS.md @@ -1,6 +1,6 @@ --- title: GEOPOS -description: The `GEOPOS` command in DiceDB is used to return the longitude, latitude to a specified key, as stored in the sorted set. +description: The `GEOPOS` command in DiceDB is used to return the longitude, latitude to a specified key, as stored in the sorted set. --- The `GEOPOS` command in DiceDB is used to return the longitude, latitude to a specified key which is stored in a sorted set. When elements are added via `GEOADD` then they are stored in 52 bit geohash hence the values returned by `GEOPOS` might have small margins of error. @@ -10,29 +10,37 @@ The `GEOPOS` command in DiceDB is used to return the longitude, latitude to a sp ```bash GEOPOS key [member [member ...]] ``` + ## Parameters -| Parameter | Description | Type | Required | -| --------- | --------------------------------------------------------------------------------- | ------ | -------- | -| key | The name of the sorted set key whose member's coordinates are to be returned | string | Yes | -| member | A unique identifier for the location. | string | Yes | + +| Parameter | Description | Type | Required | +| --------- | ---------------------------------------------------------------------------- | ------ | -------- | +| key | The name of the sorted set key whose member's coordinates are to be returned | string | Yes | +| member | A unique identifier for the location. | string | Yes | + ## Return Values -| Condition | Return Value | -| ------------------------------------------------------------ | ----------------------------------------------------------- | -| Coordinates exist for the specified member(s) | Returns an ordered list of coordinates (longitude, latitude) for each specified member | -| Coordinates do not exist for the specified member(s) | Returns `(nil)` for each member without coordinates -| Incorrect Argument Count |`ERR wrong number of arguments for 'geopos' command` | -| Key does not exist in the sorted set |`Error: nil` | + +| Condition | Return Value | +| ---------------------------------------------------- | -------------------------------------------------------------------------------------- | +| Coordinates exist for the specified member(s) | Returns an ordered list of coordinates (longitude, latitude) for each specified member | +| Coordinates do not exist for the specified member(s) | Returns `(nil)` for each member without coordinates | +| Incorrect Argument Count | `ERR wrong number of arguments for 'geopos' command` | +| Key does not exist in the sorted set | `Error: nil` | + ## Behaviour + When the GEOPOS command is issued, DiceDB performs the following steps: + 1. It checks if argument count is valid or not. If not an error is thrown. 2. It checks the validity of the key. 3. If the key is invalid then an error is returned. 4. Else it checks the members provided after the key. 5. For each member it checks the coordinates of the member. 6. If the coordinates exist then it is returned in an ordered list of latitude, longitude for the particular member. -7. If the coordinates do not exist then a ``(nil)`` is returned for that member. +7. If the coordinates do not exist then a `(nil)` is returned for that member. ## Errors + 1. `Wrong number of arguments for 'GEOPOS' command` - Error Message: (error) ERR wrong number of arguments for 'geoadd' command. - Occurs when the command is executed with an incorrect number of arguments. @@ -43,7 +51,9 @@ When the GEOPOS command is issued, DiceDB performs the following steps: ## Example Usage Here are a few examples demonstrating the usage of the GEOPOS command: + ### Example: Fetching the latitude, longitude of an existing member of the set + ```bash 127.0.0.1:7379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" 2 @@ -51,8 +61,10 @@ Here are a few examples demonstrating the usage of the GEOPOS command: 1) 1) 13.361387 2) 38.115556 ``` + ### Example: Fetching the latitude, longitude of a member not in the set + ```bash 127.0.0.1:7379> GEOPOS Sicily "Agrigento" 1) (nil) -``` \ No newline at end of file +``` diff --git a/docs/src/content/docs/commands/HINCRBY.md b/docs/src/content/docs/commands/HINCRBY.md index 1261719da..a975b87d2 100644 --- a/docs/src/content/docs/commands/HINCRBY.md +++ b/docs/src/content/docs/commands/HINCRBY.md @@ -157,4 +157,4 @@ Incrementing the hash value with a very large integer results in an integer over ## Notes -- The `HINCRBY` command is a powerful tool for managing counters and numerical values stored in hash fields, making it essential for applications that rely on incremental updates. \ No newline at end of file +- The `HINCRBY` command is a powerful tool for managing counters and numerical values stored in hash fields, making it essential for applications that rely on incremental updates. diff --git a/docs/src/content/docs/commands/HINCRBYFLOAT.md b/docs/src/content/docs/commands/HINCRBYFLOAT.md index 3f12489f8..1d9d464a2 100644 --- a/docs/src/content/docs/commands/HINCRBYFLOAT.md +++ b/docs/src/content/docs/commands/HINCRBYFLOAT.md @@ -136,4 +136,4 @@ Executing `hincrbyfloat` with a string increment value - The `HINCRBYFLOAT` command is a powerful tool for managing floating-point counters and numerical values stored in hash fields, making it essential for applications that require precision in incremental updates. - The command operates atomically, meaning it will complete without interruption, making it safe to use in concurrent environments where multiple clients may modify the same hash fields. -- `HINCRBYFLOAT` can be beneficial in scenarios such as tracking scores in a game, maintaining balances in accounts, or managing quantities in inventory systems where floating-point values are common. \ No newline at end of file +- `HINCRBYFLOAT` can be beneficial in scenarios such as tracking scores in a game, maintaining balances in accounts, or managing quantities in inventory systems where floating-point values are common. diff --git a/docs/src/content/docs/commands/HRANDFIELD.md b/docs/src/content/docs/commands/HRANDFIELD.md index 4fe6811c6..173643e1b 100644 --- a/docs/src/content/docs/commands/HRANDFIELD.md +++ b/docs/src/content/docs/commands/HRANDFIELD.md @@ -128,4 +128,4 @@ Passing invalid number of arguments to the `hrandfield` command ## Notes - The `HRANDFIELD` command is useful for scenarios where random selection from hash fields is required, such as in games, lotteries, or randomized surveys. -- The command can return multiple fields at once, allowing for efficient random sampling without the need for multiple calls. This can be particularly advantageous when working with larger hashes. \ No newline at end of file +- The command can return multiple fields at once, allowing for efficient random sampling without the need for multiple calls. This can be particularly advantageous when working with larger hashes. diff --git a/docs/src/content/docs/commands/INCR.md b/docs/src/content/docs/commands/INCR.md index 208658e4d..15210f268 100644 --- a/docs/src/content/docs/commands/INCR.md +++ b/docs/src/content/docs/commands/INCR.md @@ -94,4 +94,4 @@ Incrementing a key `mykey` with a value that exceeds the maximum integer value: ## Alternatives - You can also use the [`INCRBY`](/commands/incrby) command to increment the value of a key by a specified amount. -- You can also use the [`INCRBYFLOAT`](/commands/incrbyfloat) command to increment the value of a key by a fractional amount. \ No newline at end of file +- You can also use the [`INCRBYFLOAT`](/commands/incrbyfloat) command to increment the value of a key by a fractional amount. diff --git a/docs/src/content/docs/commands/JSON.OBJLEN.md b/docs/src/content/docs/commands/JSON.OBJLEN.md index 5c756348c..a92289c06 100644 --- a/docs/src/content/docs/commands/JSON.OBJLEN.md +++ b/docs/src/content/docs/commands/JSON.OBJLEN.md @@ -22,13 +22,13 @@ JSON.OBJLEN key [path] ## Return values -| Condition | Return Value | -| ------------------------------- | ------------------------------------------------------------------------------------------- | -| Command is successful | `Integer` denoting the number of keys length of the list at the specified key. | -| Wrong number of arguments | Error: `(error) ERR wrong number of arguments for JSON.OBJLEN command` | -| Key does not exist | Error: `(error) ERR could not perform this operation on a key that doesn't exist` | -| Key is not for a JSON object | Error: `(error) ERR WRONGTYPE Operation against a key holding the wrong kind of value` | -| Path malformed or doesn't exist | Error: `(error) ERR Path 'foo' does not exist` | +| Condition | Return Value | +| ------------------------------- | -------------------------------------------------------------------------------------- | +| Command is successful | `Integer` denoting the number of keys length of the list at the specified key. | +| Wrong number of arguments | Error: `(error) ERR wrong number of arguments for JSON.OBJLEN command` | +| Key does not exist | Error: `(error) ERR could not perform this operation on a key that doesn't exist` | +| Key is not for a JSON object | Error: `(error) ERR WRONGTYPE Operation against a key holding the wrong kind of value` | +| Path malformed or doesn't exist | Error: `(error) ERR Path 'foo' does not exist` | ## Behaviour @@ -70,15 +70,16 @@ Get number of keys in the Root JSON Object. You can specify the JSON root using 127.0.0.1:7379> JSON.OBJLEN a $ 1) 3 ``` + It returns 3, because there are three root keys in the root JSON object: `name`, `age`, and `address`. Or, if you don't want to specify a JSON path, it may be omitted. The path defaults to the root, and the result is given as a scalar: + ```bash 127.0.0.1:7379> JSON.OBJLEN a 3 ``` - ### Keys inside nested object To count the number of keys inside a nested object, specify a JSON Path. The root of the JSON object is referred to by the `$` symbol. @@ -89,6 +90,7 @@ To count the number of keys inside a nested object, specify a JSON Path. The roo 127.0.0.1:7379> JSON.OBJLEN b $.address 1) 3 ``` + Here, it returns 3 because it's counting the three keys inside the `$.address` JSON object: `city`, `state`, and `zipcode`. ### When path is not a JSON object diff --git a/docs/src/content/docs/commands/LINSERT.md b/docs/src/content/docs/commands/LINSERT.md index c00f4858d..7be8ba0a7 100644 --- a/docs/src/content/docs/commands/LINSERT.md +++ b/docs/src/content/docs/commands/LINSERT.md @@ -98,4 +98,4 @@ OK - Check Key Type: Before using `LINSERT`, ensure that the key is associated with a list to avoid errors. - Handle Non-Existent Keys: Be prepared to handle the case where the key does not exist, as `LINSERT` will return `0` in such scenarios. -- Use in Conjunction with Other List Commands: The `LINSERT` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LPUSH`](/commands/lpush), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. \ No newline at end of file +- Use in Conjunction with Other List Commands: The `LINSERT` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LPUSH`](/commands/lpush), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. diff --git a/docs/src/content/docs/commands/LLEN.md b/docs/src/content/docs/commands/LLEN.md index 2c70581f1..a0b501419 100644 --- a/docs/src/content/docs/commands/LLEN.md +++ b/docs/src/content/docs/commands/LLEN.md @@ -84,4 +84,4 @@ OK - Check Key Type: Before using `LLEN`, ensure that the key is associated with a list to avoid errors. - Handle Non-Existent Keys: Be prepared to handle the case where the key does not exist, as `LLEN` will return `0` in such scenarios. -- Use in Conjunction with Other List Commands: The `LLEN` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LPUSH`](/commands/lpush), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. \ No newline at end of file +- Use in Conjunction with Other List Commands: The `LLEN` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LPUSH`](/commands/lpush), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. diff --git a/docs/src/content/docs/commands/LPOP.md b/docs/src/content/docs/commands/LPOP.md index fcf6e9249..54918e521 100644 --- a/docs/src/content/docs/commands/LPOP.md +++ b/docs/src/content/docs/commands/LPOP.md @@ -113,4 +113,4 @@ LPOP mylist secondlist - `Handle Non-Existent Keys`: Be prepared to handle the case where the key does not exist, as `LPOP` will return `nil` in such scenarios. - `Use in Conjunction with Other List Commands`: The `LPOP` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LPUSH`](/commands/lpush), [`LLEN`](/commands/llen), and [`RPOP`](/commands/rpop) to manage and process lists effectively. -By understanding and using the `LPOP` command effectively, you can manage list data structures in DiceDB efficiently, implementing queue-like behaviors and more. \ No newline at end of file +By understanding and using the `LPOP` command effectively, you can manage list data structures in DiceDB efficiently, implementing queue-like behaviors and more. diff --git a/docs/src/content/docs/commands/LPUSH.md b/docs/src/content/docs/commands/LPUSH.md index f5829e860..f882c774f 100644 --- a/docs/src/content/docs/commands/LPUSH.md +++ b/docs/src/content/docs/commands/LPUSH.md @@ -101,4 +101,4 @@ LPUSH mylist - `Use in Conjunction with Other List Commands`: The `LPUSH` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LLEN`](/commands/llen), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. - The `LPUSH` command can be used to implement a stack (LIFO) by always pushing new elements to the head of the list. -By understanding the `LPUSH` command, you can efficiently manage lists in DiceDB, ensuring that elements are added to the head of the list as needed. \ No newline at end of file +By understanding the `LPUSH` command, you can efficiently manage lists in DiceDB, ensuring that elements are added to the head of the list as needed. diff --git a/docs/src/content/docs/commands/LRANGE.md b/docs/src/content/docs/commands/LRANGE.md index 4e4d62381..76023960d 100644 --- a/docs/src/content/docs/commands/LRANGE.md +++ b/docs/src/content/docs/commands/LRANGE.md @@ -111,4 +111,4 @@ OK - Check Key Type: Before using `LRANGE`, ensure that the key is associated with a list to avoid errors. - Handle Non-Existent Keys: Be prepared to handle the case where the key does not exist, as `LRANGE` will return an empty array in such scenarios. -- Use in Conjunction with Other List Commands: The `LRANGE` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LPUSH`](/commands/lpush), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. \ No newline at end of file +- Use in Conjunction with Other List Commands: The `LRANGE` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LPUSH`](/commands/lpush), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. diff --git a/docs/src/content/docs/commands/PTTL.md b/docs/src/content/docs/commands/PTTL.md index 933466427..43d998eb4 100644 --- a/docs/src/content/docs/commands/PTTL.md +++ b/docs/src/content/docs/commands/PTTL.md @@ -85,4 +85,4 @@ In this example, the `PTTL` command is used with an extra argument. This results ## Alternatives -- [`TTL`](/commands/ttl): Similar to `PTTL` but returns the time-to-live in seconds instead of milliseconds \ No newline at end of file +- [`TTL`](/commands/ttl): Similar to `PTTL` but returns the time-to-live in seconds instead of milliseconds diff --git a/docs/src/content/docs/commands/RPOP.md b/docs/src/content/docs/commands/RPOP.md index 0fb5407cf..941e43165 100644 --- a/docs/src/content/docs/commands/RPOP.md +++ b/docs/src/content/docs/commands/RPOP.md @@ -91,4 +91,4 @@ RPOP mylist secondlist - `Handle Non-Existent Keys`: Be prepared to handle the case where the key does not exist, as `RPOP` will return `nil` in such scenarios. - `Use in Conjunction with Other List Commands`: The `RPOP` command is often used alongside other list commands like [`RPUSH`](/commands/rpush), [`LPUSH`](/commands/lpush), [`LLEN`](/commands/llen), and [`LPOP`](/commands/lpop) to manage and process lists effectively. -By understanding the `RPOP` command, you can effectively manage lists in DiceDB, ensuring that you can retrieve and process elements in a LIFO order. \ No newline at end of file +By understanding the `RPOP` command, you can effectively manage lists in DiceDB, ensuring that you can retrieve and process elements in a LIFO order. diff --git a/docs/src/content/docs/commands/RPUSH.md b/docs/src/content/docs/commands/RPUSH.md index b8163e382..f6fce3d65 100644 --- a/docs/src/content/docs/commands/RPUSH.md +++ b/docs/src/content/docs/commands/RPUSH.md @@ -87,4 +87,4 @@ RPUSH mylist ## Best Practices - `Check Key Type`: Before using `RPUSH`, ensure that the key is associated with a list to avoid errors. -- `Use in Conjunction with Other List Commands`: The `RPUSH` command is often used alongside other list commands like [`LLEN`](/commands/llen), [`LPUSH`](/commands/lpush), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. \ No newline at end of file +- `Use in Conjunction with Other List Commands`: The `RPUSH` command is often used alongside other list commands like [`LLEN`](/commands/llen), [`LPUSH`](/commands/lpush), [`LPOP`](/commands/lpop), and [`RPOP`](/commands/rpop) to manage and process lists effectively. diff --git a/docs/src/content/docs/commands/SETEX.md b/docs/src/content/docs/commands/SETEX.md index 7415a2173..4567d66e5 100644 --- a/docs/src/content/docs/commands/SETEX.md +++ b/docs/src/content/docs/commands/SETEX.md @@ -17,18 +17,18 @@ SETEX key seconds value ## Parameters -| Parameter | Description | Type | Required | -| --------- | ------------------------------------------------------------------------- | ------- | -------- | -| `key` | The name of the key to be set. | String | Yes | -| `seconds` | Expiration time for the key in seconds. | Integer | Yes | -| `value` | The value to be set for the key. | Integer | No | +| Parameter | Description | Type | Required | +| --------- | --------------------------------------- | ------- | -------- | +| `key` | The name of the key to be set. | String | Yes | +| `seconds` | Expiration time for the key in seconds. | Integer | Yes | +| `value` | The value to be set for the key. | Integer | No | ## Return values -| Condition | Return Value | -| ------------------------------------------- | ----------------------------------------------- | -| Command is successful | `OK` | -| Syntax or specified constraints are invalid | error | +| Condition | Return Value | +| ------------------------------------------- | ------------ | +| Command is successful | `OK` | +| Syntax or specified constraints are invalid | error | ## Behaviour @@ -78,10 +78,12 @@ Setting a key with an invalid expiration time will result in an error: ``` Attempting to use the command with missing arguments will result in an error: + ```bash 127.0.0.1:7379> SETEX foo 10 (error) ERROR wrong number of arguments for 'setex' command ``` ### Notes: + `SETEX` can be replaced via [`SET`](/commands/set) with `EX` option. diff --git a/docs/src/content/docs/commands/SMEMBERS.md b/docs/src/content/docs/commands/SMEMBERS.md index 1d7c23157..0207ba100 100644 --- a/docs/src/content/docs/commands/SMEMBERS.md +++ b/docs/src/content/docs/commands/SMEMBERS.md @@ -89,4 +89,4 @@ OK 1. The command returns all members at once, which may impact performance for very large sets 2. The order of returned elements is not guaranteed and may vary between calls 3. Memory usage scales linearly with the size of the set -4. This command has O(N) time complexity where N is the set size \ No newline at end of file +4. This command has O(N) time complexity where N is the set size diff --git a/docs/src/content/docs/commands/TTL.md b/docs/src/content/docs/commands/TTL.md index aef736326..8d6779091 100644 --- a/docs/src/content/docs/commands/TTL.md +++ b/docs/src/content/docs/commands/TTL.md @@ -85,4 +85,4 @@ In this example, the `TTL` command is used with an extra argument. This results ## Alternatives -- [`PTTL`](/commands/pttl): Similar to `TTL` but returns the time-to-live in milliseconds instead of seconds \ No newline at end of file +- [`PTTL`](/commands/pttl): Similar to `TTL` but returns the time-to-live in milliseconds instead of seconds diff --git a/docs/src/content/docs/commands/ZRANK.md b/docs/src/content/docs/commands/ZRANK.md index 777dc027f..1ff619d05 100644 --- a/docs/src/content/docs/commands/ZRANK.md +++ b/docs/src/content/docs/commands/ZRANK.md @@ -80,4 +80,4 @@ Retrieve both the rank and the score of `member2` in the sorted set `myzset`: ## Notes -- This command is particularly useful for implementing leaderboards, pagination in ranked lists, and analytics on data distribution. \ No newline at end of file +- This command is particularly useful for implementing leaderboards, pagination in ranked lists, and analytics on data distribution. diff --git a/docs/src/content/docs/get-started/hello-world.mdx b/docs/src/content/docs/get-started/hello-world.mdx index 5cd0621a4..692dc26a3 100644 --- a/docs/src/content/docs/get-started/hello-world.mdx +++ b/docs/src/content/docs/get-started/hello-world.mdx @@ -17,7 +17,7 @@ You can follow the steps mentioned in the [installation](/get-started/installati Once the DiceDB server starts, you will see output similar to this ``` - ██████╗ ██╗ ██████╗███████╗██████╗ ██████╗ + ██████╗ ██╗ ██████╗███████╗██████╗ ██████╗ ██╔══██╗██║██╔════╝██╔════╝██╔══██╗██╔══██╗ ██║ ██║██║██║ █████╗ ██║ ██║██████╔╝ ██║ ██║██║██║ ██╔══╝ ██║ ██║██╔══██╗ diff --git a/docs/src/content/docs/get-started/realtime-leaderboard.mdx b/docs/src/content/docs/get-started/realtime-leaderboard.mdx index b47d0e38b..b59ee1ad9 100644 --- a/docs/src/content/docs/get-started/realtime-leaderboard.mdx +++ b/docs/src/content/docs/get-started/realtime-leaderboard.mdx @@ -32,7 +32,7 @@ docker run -p 7379:7379 dicedb/dicedb --enable-watch Once the DiceDB server starts, you will see output similar to this ``` - ██████╗ ██╗ ██████╗███████╗██████╗ ██████╗ + ██████╗ ██╗ ██████╗███████╗██████╗ ██████╗ ██╔══██╗██║██╔════╝██╔════╝██╔══██╗██╔══██╗ ██║ ██║██║██║ █████╗ ██║ ██║██████╔╝ ██║ ██║██║██║ ██╔══╝ ██║ ██║██╔══██╗ diff --git a/docs/src/content/docs/tutorials/url-shortener.md b/docs/src/content/docs/tutorials/url-shortener.md index fb47fd2d6..40d790e9c 100644 --- a/docs/src/content/docs/tutorials/url-shortener.md +++ b/docs/src/content/docs/tutorials/url-shortener.md @@ -13,15 +13,19 @@ This tutorial guides you through creating a URL shortener using DiceDB, a key-va ## Setup ### 1. Install and Run DiceDB + Start a DiceDB server using Docker: -```bash + +```bash docker run -d -p 7379:7379 dicedb/dicedb ``` - + This command pulls the DiceDB Docker image and runs it, exposing it on port `7379`. ### 2. Initialize a New Go Project + Create a new directory for your project and initialize a Go module: + ```bash mkdir url-shortener cd url-shortener @@ -29,7 +33,9 @@ go mod init url-shortener ``` ### 3. Install Required Packages + Install the DiceDB Go SDK and other dependencies: + ```bash go get github.com/dicedb/dicedb-go go get github.com/gin-gonic/gin @@ -37,119 +43,130 @@ go get github.com/google/uuid ``` ## Understanding DiceDB Commands + We'll use the following DiceDB commands: + ### `SET` Command + Stores a key-value pair in DiceDB. + - **Syntax**: `SET key value [expiration]` - `key`: Unique identifier (e.g., short URL code) - `value`: Data to store (e.g., serialized JSON) - `expiration`: Optional; time-to-live in seconds (use `0` for no expiration) + ### `GET` Command + Retrieves the value associated with a key. + - **Syntax**: `GET key` - `key`: Identifier for the data to retrieve ## Writing the Code + Create a file named `main.go` and add the following code: - `main.go`: - ```go - package main - - import ( - "context" - "encoding/json" - "log" - "net/http" - - "github.com/gin-gonic/gin" - "github.com/google/uuid" - "github.com/dicedb/dicedb-go" // DiceDB Go SDK - ) - - type URL struct { - ID string `json:"id"` - LongURL string `json:"long_url"` - ShortURL string `json:"short_url"` - } - - var db *dicedb.Client - - // Initialize DiceDB connection - func init() { - db = dicedb.NewClient(&dicedb.Options{ - Addr: "localhost:7379", - }) - } - - // Creates a short URL from a given long URL - func CreateShortURL(c *gin.Context) { - var requestBody URL - if err := c.ShouldBindJSON(&requestBody); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) - return - } - - // Generate unique short ID and construct the short URL - shortID := uuid.New().String()[:8] - requestBody.ID = shortID - requestBody.ShortURL = "http://localhost:8080/" + shortID - - // Serialize URL struct to JSON and store it in DiceDB - urlData, err := json.Marshal(requestBody) - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) - return - } - - if err := db.Set(context.Background(), shortID, urlData, 0).Err(); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) - return - } - - c.JSON(http.StatusCreated, gin.H{"short_url": requestBody.ShortURL}) - } - - // Redirects to the original URL based on the short URL ID - func RedirectURL(c *gin.Context) { - id := c.Param("id") - - // Retrieve stored URL data from DiceDB - urlData, err := db.Get(context.Background(), id).Result() - if err != nil { - c.JSON(http.StatusNotFound, gin.H{"error": "URL not found"}) - return - } - - // Deserialize JSON data back into URL struct - var url URL - if err := json.Unmarshal([]byte(urlData), &url); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to decode URL data"}) - return - } - - // Redirect user to the original long URL - c.Redirect(http.StatusFound, url.LongURL) - } - - func main() { - router := gin.Default() - - // Define endpoints for creating short URLs and redirecting - router.POST("/shorten", CreateShortURL) - router.GET("/:id", RedirectURL) - - // Start the server on port 8080 - if err := router.Run(":8080"); err != nil { - log.Fatal("Failed to start server:", err) - } - } - ``` + + ```go + package main + + import ( + "context" + "encoding/json" + "log" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "github.com/dicedb/dicedb-go" // DiceDB Go SDK + ) + + type URL struct { + ID string `json:"id"` + LongURL string `json:"long_url"` + ShortURL string `json:"short_url"` + } + + var db *dicedb.Client + + // Initialize DiceDB connection + func init() { + db = dicedb.NewClient(&dicedb.Options{ + Addr: "localhost:7379", + }) + } + + // Creates a short URL from a given long URL + func CreateShortURL(c *gin.Context) { + var requestBody URL + if err := c.ShouldBindJSON(&requestBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request"}) + return + } + + // Generate unique short ID and construct the short URL + shortID := uuid.New().String()[:8] + requestBody.ID = shortID + requestBody.ShortURL = "http://localhost:8080/" + shortID + + // Serialize URL struct to JSON and store it in DiceDB + urlData, err := json.Marshal(requestBody) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + if err := db.Set(context.Background(), shortID, urlData, 0).Err(); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to save URL"}) + return + } + + c.JSON(http.StatusCreated, gin.H{"short_url": requestBody.ShortURL}) + } + + // Redirects to the original URL based on the short URL ID + func RedirectURL(c *gin.Context) { + id := c.Param("id") + + // Retrieve stored URL data from DiceDB + urlData, err := db.Get(context.Background(), id).Result() + if err != nil { + c.JSON(http.StatusNotFound, gin.H{"error": "URL not found"}) + return + } + + // Deserialize JSON data back into URL struct + var url URL + if err := json.Unmarshal([]byte(urlData), &url); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to decode URL data"}) + return + } + + // Redirect user to the original long URL + c.Redirect(http.StatusFound, url.LongURL) + } + + func main() { + router := gin.Default() + + // Define endpoints for creating short URLs and redirecting + router.POST("/shorten", CreateShortURL) + router.GET("/:id", RedirectURL) + + // Start the server on port 8080 + if err := router.Run(":8080"); err != nil { + log.Fatal("Failed to start server:", err) + } + } + ``` ## Explanation ### 1. Initialize the DiceDB Client + We set up the DiceDB client in the `init` function: + ```go db = dicedb.NewClient(&dicedb.Options{ Addr: "localhost:7379", @@ -157,6 +174,7 @@ db = dicedb.NewClient(&dicedb.Options{ ``` ### 2. Create Short URL Endpoint + - **Input Validation**: Ensures the `long_url` field is present. - **Short ID Generation**: Uses `uuid` to create a unique 8-character ID. - **Data Serialization**: Converts the `URL` struct to JSON. @@ -164,50 +182,62 @@ db = dicedb.NewClient(&dicedb.Options{ - **Response**: Returns the generated short URL. ### 3. Redirect to Original URL Endpoint + - **Data Retrieval**: Fetches the URL data from DiceDB using the `Get` command. - **Data Deserialization**: Converts JSON back to the `URL` struct. - **Redirection**: Redirects the user to the `LongURL`. ### 4. Start the Server + The `main` function sets up the routes and starts the server on port `8080`. ## Running the Application ### 1. Start the Go Application + ```bash go run main.go ``` + This will start the application server on port 8080 by default, you should see output similar to + ```bash [GIN-debug] Listening and serving HTTP on :8080 ``` ### 2. Ensure DiceDB is Running + Ensure your DiceDB server is up and running on port `7379`. ## Testing the application ### 1. Shorten URL: + **Using `curl`:** + ```bash curl -X POST -H "Content-Type: application/json" -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten ``` **Response:** + ```json { -"short_url": "http://localhost:8080/" + "short_url": "http://localhost:8080/" } ``` ### 2. Redirect to Original URL: + **Using `curl`:** + ```bash curl -L http://localhost:8080/abcd1234 ``` - + **Using a Browser:** Navigate to: + ``` http://localhost:8080/abcd1234 ``` diff --git a/docs/src/content/team/apoorv.json b/docs/src/content/team/apoorv.json new file mode 100644 index 000000000..737063252 --- /dev/null +++ b/docs/src/content/team/apoorv.json @@ -0,0 +1,10 @@ +{ + "name": "Apoorv Yadav", + "avatar_url": "https://avatars.githubusercontent.com/u/32174554?v=4", + "url": "", + "x": "", + "linkedin": "https://www.linkedin.com/in/yadavapoorv/", + "github": "https://github.com/apoorvyadav1111", + "website": "", + "roles": ["committer"] +} diff --git a/docs/src/content/team/arpit.json b/docs/src/content/team/arpit.json new file mode 100644 index 000000000..cc1a4c814 --- /dev/null +++ b/docs/src/content/team/arpit.json @@ -0,0 +1,10 @@ +{ + "name": "Arpit Bhayani", + "avatar_url": "https://edge.arpitbhayani.me/img/arpit-2.png", + "url": "https://arpitbhayani.me/", + "x": "https://x.com/arpit_bhayani", + "linkedin": "https://linkedin.com/in/arpitbhayani", + "github": "https://github.com/arpitbbhayani", + "website": "https://arpitbhayani.me/", + "roles": ["pmc"] +} diff --git a/docs/src/content/team/ashwin.json b/docs/src/content/team/ashwin.json new file mode 100644 index 000000000..bfc98426b --- /dev/null +++ b/docs/src/content/team/ashwin.json @@ -0,0 +1,10 @@ +{ + "name": "Ashwin Kulkarni", + "avatar_url": "https://avatars.githubusercontent.com/u/19169648?v=4", + "url": "", + "x": "https://x.com/ashwinkulkarni4", + "linkedin": "https://www.linkedin.com/in/iashwin28/", + "github": "https://github.com/AshwinKul28", + "website": "", + "roles": ["pmc"] +} diff --git a/docs/src/content/team/jyotinder.json b/docs/src/content/team/jyotinder.json new file mode 100644 index 000000000..b6ad4984b --- /dev/null +++ b/docs/src/content/team/jyotinder.json @@ -0,0 +1,10 @@ +{ + "name": "Jyotinder Singh", + "avatar_url": "https://avatars.githubusercontent.com/u/33001894?v=4", + "url": "https://jyotindersingh.com/", + "x": "https://x.com/Jyotinder_Singh", + "linkedin": "https://linkedin.com/in/jyotinder-singh", + "github": "https://github.com/JyotinderSingh", + "website": "https://jyotindersingh.com/", + "roles": ["pmc"] +} diff --git a/docs/src/content/team/prashant.json b/docs/src/content/team/prashant.json new file mode 100644 index 000000000..561ce56ec --- /dev/null +++ b/docs/src/content/team/prashant.json @@ -0,0 +1,10 @@ +{ + "name": "Prashant Shubham", + "avatar_url": "https://avatars.githubusercontent.com/u/13472823?v=4", + "url": "https://prasha.me", + "x": "https://x.com/prashacr7", + "linkedin": "https://www.linkedin.com/in/prashant-shubham07", + "github": "https://github.com/lucifercr07", + "website": "https://prasha.me", + "roles": ["pmc"] +} diff --git a/docs/src/content/team/prateek.json b/docs/src/content/team/prateek.json new file mode 100644 index 000000000..c62fc8bf0 --- /dev/null +++ b/docs/src/content/team/prateek.json @@ -0,0 +1,10 @@ +{ + "name": "Prateek Rathore", + "avatar_url": "https://avatars.githubusercontent.com/u/25244718?v=4", + "url": "", + "x": "https://twitter.com/psrvere", + "linkedin": "https://www.linkedin.com/in/prateek-singh-rathore/", + "github": "https://github.com/psrvere", + "website": "", + "roles": ["committer"] +} diff --git a/docs/src/content/team/soumya.json b/docs/src/content/team/soumya.json new file mode 100644 index 000000000..584d42e0a --- /dev/null +++ b/docs/src/content/team/soumya.json @@ -0,0 +1,10 @@ +{ + "name": "Soumya Panigrahi", + "avatar_url": "https://avatars.githubusercontent.com/u/151079203?v=4", + "url": "", + "x": "https://x.com/soumyapanigrahi", + "linkedin": "https://www.linkedin.com/in/soumya-panigrahi-8038118/", + "github": "https://github.com/soumya-codes", + "website": "", + "roles": ["pmc"] +} diff --git a/docs/src/content/updates/2024-07-18.md b/docs/src/content/updates/2024-07-18.md new file mode 100644 index 000000000..db0b615c6 --- /dev/null +++ b/docs/src/content/updates/2024-07-18.md @@ -0,0 +1,14 @@ +--- +--- + +Agenda: + +- First community call 🎉 +- The documentation website is up: [https://dicedb-docs.netlify.app/](https://dicedb-docs.netlify.app/) +- Plan to keep DiceDB a drop-in replacement of Redis, however, redis feature-set completion won’t be a blocker for launch. +- Aim to support a basic, foundational feature set +- Plans for real-time reactivity: +- Support for JSON +- Filtering on JSON fields +- Optimizations for DSQL query executor: +- Instead of re.match use a specific regex matcher for better performance. diff --git a/docs/src/content/updates/2024-08-01.md b/docs/src/content/updates/2024-08-01.md new file mode 100644 index 000000000..5c5b8a28a --- /dev/null +++ b/docs/src/content/updates/2024-08-01.md @@ -0,0 +1,25 @@ +--- +--- + +Agenda: + +- Updates from Arpit +- Design discussion around multi-threaded architecture for Dice being implemented by Yash +- JSON integration with QWATCH +- Add JSON support to the executor to filter on JSON fields using JSONPath syntax. +- JSON-to-JSON comparisons in WHERE clause? +- Research from Cockroach labs on Json libs \- [https://www.cockroachlabs.com/blog/high-performance-json-parsing/](https://www.cockroachlabs.com/blog/high-performance-json-parsing/) + +## Jul 25, 2024 | [DiceDB Weekly Community Call](https://www.google.com/calendar/event?eid=M2Judmhnb2E0YnFsY2d0NWUwMDBhdnZjbmUgYXJwaXQubWFzdGVyY2xhc3NAbQ) + +Agenda: + +- Commands for supporting JSON as native Data Type \- do we agree on [this](https://redis.io/docs/latest/develop/data-types/json/). I see the issue has already been created, we just need an alignment. +- Jyotinder to check for absolute essentials for Realtime Reactivity +- Crips documentation around the DSQL capabilities as of today +- JSON support for JSONPath and partial updates +- Yash to discuss multi-threaded implementation +- ByteArray divergence \- BITX commands for ByteArray type +- String and ByteArray implementation will have different performance +- Make sure this is documented +- Arpit to write documentation around \`SET\` and \`GET\` command in docs repository. diff --git a/docs/src/content/updates/2024-08-08.md b/docs/src/content/updates/2024-08-08.md new file mode 100644 index 000000000..1ea195eb6 --- /dev/null +++ b/docs/src/content/updates/2024-08-08.md @@ -0,0 +1,47 @@ +--- +--- + +Shipped 🚀 + +- Command Enhancements: +- KEYS command implementation +- SET command enhancements +- COMMAND GETKEYS command added +- MSET command implementation +- JSON Support: +- JSON.SET and JSON.GET commands +- JSONPath support for querying JSON data +- AUTH command +- BIT commands +- Performance and Stability: +- Fixed server reconnection issues +- Key Expiry fixes +- Executor Benchmarks added +- Thread safety improvements for dencoding +- Data Handling: +- RESP parsing fix for handling RESP_NIL in BulkString +- Signed integer dencoding support +- Development and Testing: +- Test improvements +- Live Reloading on dev server + +Agenda: + +- soumya: Do we need to support range queries? +- gaurav897: _Do we have a good monitoring/metrics/logging story around DiceDB? Given that we are early in the project, should we start proactively on this?_ +- Prometheus +- opentelemetry +- Executor performance +- [https://discord.com/channels/1034342738960855120/1264145943884992595/1269314643298488370](https://discord.com/channels/1034342738960855120/1264145943884992595/1269314643298488370) +- Integration test setup? + +Action Items + +- Memtier +- SQL equivalence +- JSON where clause support +- dice-cli stability with QWATCH +- Python-sdk +- Java-sdk +- Js-sdk +- Stripped locking diff --git a/docs/src/content/updates/2024-08-15.md b/docs/src/content/updates/2024-08-15.md new file mode 100644 index 000000000..c56fce2c0 --- /dev/null +++ b/docs/src/content/updates/2024-08-15.md @@ -0,0 +1,44 @@ +--- +--- + +Shipped + +- Commands: +- TOUCH and OBJECT IDLETIME +- KEEPTTL option for SET command +- COPY command +- PTTL command +- GETEX command +- GETDEL command +- RENAME command +- MGET command +- DECRBY command +- EXISTS command +- DECR command +- Fixes +- Fixed atomicity issue in GetAll() function +- Improved atomicity of Get() function +- Simplified AUTH flow +- Fixed failing TestJSONSetWithInvalidJSON +- Fixed issue with emitting watchEvent from DelByPointer +- Testing and code quality: +- Added script to plot executor benchmark results +- Added various new test cases: +- For DEL command +- For DISCARD command +- For expired keys in StackRef.Pop() method +- Additional unit tests for eval.go file +- Introduced golangci linter to improve code quality +- Improved queueref benchmark + +## Discussion + +- Consensus on consistency - Do we need locks, readers-writers block, etc. +- Blocking operations +- Gaurav and Soumya to explain their reasoning + +## Action Items + +- New In memory shard for serving watch queries. +- Make target for linting +- Sleep Timer stub diff --git a/docs/src/content/updates/2024-08-19.md b/docs/src/content/updates/2024-08-19.md new file mode 100644 index 000000000..a74b13181 --- /dev/null +++ b/docs/src/content/updates/2024-08-19.md @@ -0,0 +1,29 @@ +--- +--- + +Discussed: + +Separation of Concerns: + +- Commands like MGET/MSET - Key used across shards, +- Similar for Qwatch - when we are watching a pattern, the pattern can exist across multiple shards. +- Transactional commands like MGET/MSET - We need an abstraction layer outside shards that can manage the transaction across teh shards. + +IOLayer - Should it wait for all shards to complete the tasks, proceed only after all shards have responded. + +Keep store dumb. All ops on store as atomic as possible. +. Add complexity to IOLayer / Coordinator in future if optimisation are needed in future. + +Next step task + +- Remove locks and provide atomic operations. +- Address review comments and merge Store abstraction refactor Yash +- Watch to move out of store / Or implement a scan operator in store Jyotinder +- Limit Store operations to Put / Get / Delete & Scan Pratik +- We are using unsafe pointer, should we move to empty struct ot interface. Move to generics. Ashwin Kulkarni +- Removing all Mutex from Store after the shards and channels are created for multi threads. soumya +- Skeleton for multithreaded mode Yash +- Extract Coordinator from IO Tasks. Gaurav +- Qwatch: each io thread launches a qwatch command, this fans out to every shard. Each shard now maintains records for which io threads are listening to which queries . Jyotinder +- moar thoughts - the watchlist can be maintained at the said coordinator level +- Fanout commands that require consistency soumya diff --git a/docs/src/content/updates/2024-08-22.md b/docs/src/content/updates/2024-08-22.md new file mode 100644 index 000000000..0c2ea6cdb --- /dev/null +++ b/docs/src/content/updates/2024-08-22.md @@ -0,0 +1,54 @@ +--- +--- + +## Changelog + +### New Commands + +- Support for JSON.TYPE command +- Support for EXPIREAT command +- Support for DBSIZE command +- Support for EXPIRETIME command +- Deque implementation for LPUSH, RPUSH, LPOP, and RPOP commands +- JSON support in WHERE clause for queries + +### Performance + +- Improved performance of JSON WHERE clause evaluation +- Refactored store abstraction as a prerequisite for multi-threading + +### Bug Fixes + +- Type deduction logic for integers and related fixes +- RENAME command now fetches the key before renaming +- Fixed QWATCH response format and executor type inference logic +- Fixed type casting logic for SET and GET commands +- Corrected INCR/DECR logic and added tests +- Fixed incorrect benchmark iterations for QueueRef +- Corrected the JSON.SET command Arity +- Standardized error messages across codebase +- Updated AUTH error message to be consistent with Redis +- Keep JSON.TYPE consistent with Redis +- Fixed flaky tests due to JSON ordering + +### Testing + +- Added unit and integration tests for EXPIRE and EXPIRETIME commands +- Added stubbed time for tests +- Run complete test suite on PRs + +### Docs + +- Created document on inconsistencies between DiceDB and Redis + +### Developer Workflow + +- Added make target for linter +- Updated linter.yml + +## Discussions + +- Compare and contrast the list of Object Types and Encoding types supported by REDIS and DiceDB. Attempt to arrive at the next set of action items. +- [https://github.com/DiceDB/dice/issues/386\#issuecomment-2303968575](https://github.com/DiceDB/dice/issues/386#issuecomment-2303968575) +- Discuss on the current implementation of Keypool and its necessity. +- [https://github.com/DiceDB/dice/issues/386](https://github.com/DiceDB/dice/issues/386) diff --git a/docs/src/content/updates/2024-08-29.md b/docs/src/content/updates/2024-08-29.md new file mode 100644 index 000000000..37c0d6f15 --- /dev/null +++ b/docs/src/content/updates/2024-08-29.md @@ -0,0 +1,40 @@ +--- +--- + +## Changelog + +### New Commands + +- Implement \`HSET\` command +- Add support for options for EXPIRE and EXPIREAT +- Add support for command \`JSON.CLEAR\` +- Added \`SADD\`, \`SREM\`, \`MEMBERS\`, \`SCARD\`, \`SINTER\`, \`SDIFF\` commands +- Implement \`GETSET\` command +- Added support for \`FLUSHDB\` command +- Add support for \`BITPOS\` command +- Added support for \`QUNWATCH\` command + +### Bug Fixes + +- Fix: \`STACKREFLEN\` and \`QUEUEREFLEN\` are not aware of the deletion of key + +### Testing + +- Add asserts checking non-set commands: addresses \#411 +- Adds memtier benchmark and load tests preset + +### General Improvements + +- Move QWATCH logic to QueryWatcher +- Reorganize async server code +- Moved from unsafe pointer to string type for the store + +## Action Items + +- Hacktoberfest focus +- Docs: Inaccuracies, fixes. +- Testing +- Dice-cli +- Language-specific SDKs +- Windows Support +- Report command inconsistencies diff --git a/docs/src/content/updates/2024-09-05.md b/docs/src/content/updates/2024-09-05.md new file mode 100644 index 000000000..0a36df74f --- /dev/null +++ b/docs/src/content/updates/2024-09-05.md @@ -0,0 +1,43 @@ +--- +--- + +## Changelog + +### New Commands + +1. Added support for JSON.DEL command +2. Implemented PFADD/PFCOUNT commands +3. Added COMMAND LIST command +4. Added support for HGETALL command + +### Features + +1. Implemented caching for QWATCH queries to improve performance +2. Added JSON support to ORDER BY clause for DSQL queries +3. Added ShardThread and ShardManager for improved concurrency +4. Switched the store to use SwissTable instead of HashTable for better performance +5. Migrated set data structure from built-in go map to swissTable + +### Bug Fixes + +1. Fixed integer type handling inconsistencies in SQL executor +2. Fixed SETBIT command for encoding +3. Fixed benchmark issue in BenchmarkEvalMSET by resetting store for each iteration + +### Testing + +1. Added integration tests for JSON.CLEAR and JSON.DEL commands +2. Temporarily reverted TCL tests integration in Dice + +### Other + +1. Removed query-watcher dependency from store +2. Updated tests to use new Map implementation +3. Fixed linting errors in SwissTable implementation + +## Action Items + +- Allow people to run queries without using cache +- Move set back to hashmap +- Set up a temporary issue for the qwatch leaderboard impl. +- Improve qwatch testing, chaos testing, try to break it. diff --git a/docs/src/content/updates/2024-09-12.md b/docs/src/content/updates/2024-09-12.md new file mode 100644 index 000000000..098de5a64 --- /dev/null +++ b/docs/src/content/updates/2024-09-12.md @@ -0,0 +1,52 @@ +--- +--- + +## Changelog + +### New Commands + +1. Added support for `JSON.ARRLEN` command +2. Implemented `HGET` command +3. Added support for `COMMAND` command + +### Features + +1. Improved `ORDER BY` clause handling in SQL parser +2. Added support for `LIKE` and `NOT LIKE` to the SQL Executor +3. Added retry with exponential backoff for QWATCH writes +4. Added support for common cache per fingerprint in QWATCH +5. Deprecated `FROM` clause in DSQL and moved key filtering to `WHERE` +6. Added realtime leaderboard demo using QWATCH + +### Bug Fixes + +1. Fixed hyperloglog type assertion check +2. Fixed inconsistent `EXPIRE` with conflicting options: `LT` `GT` +3. Fixed data race occurring when emitting a WatchEvent +4. Fixed inconsistent `EXPIRE` when ran with flags `XX`, `LT`\-`XX` and `GT` on a key without ttl +5. Fixed bitmap commands deviation from Redis implementation +6. Optimized type error return + +### Testing + +1. Added TestEnvEnabled config and avoiding AOF dump for test env +2. Added unit and integration tests for `HGET` command + +### Other + +1. Version bump +2. Notifies Query Manager of key changes asynchronously +3. Removed locking structures for store +4. Refactored constants from constants package +5. Refactored the codebase and moved packages to internal +6. Removed keypool and related structures from the store +7. Reverted set data structure to map +8. Updated README with Leaderboard example + +## Discussion + +- Stability \+ latencies +- Redis exporter, node exporter, prometheus +- TCL test documentation +- Multi-threading progress +- New query fingerprinting logic diff --git a/docs/src/content/updates/2024-09-19.md b/docs/src/content/updates/2024-09-19.md new file mode 100644 index 000000000..aa1d3db44 --- /dev/null +++ b/docs/src/content/updates/2024-09-19.md @@ -0,0 +1,64 @@ +--- +--- + +## Changelog + +### New Commands + +1. Added `JSON.INGEST` support for HTTP +2. Added `COMMAND HELP` +3. Added `JSON.ARRPOP` command +4. Implemented `JSON.NUMINCRBY` command +5. Added support for `JSON.MGET` +6. Added support for `JSON.TOGGLE` +7. Implemented `JSON.ARRAPPEND` command +8. Added support for `JSON.DEBUG` +9. Added support for `LLEN` command +10. Added support for `SELECT` command +11. Added `HLEN` support +12. Added support for `JSON.OBJLEN` +13. Added support for `JSON.STRLEN` +14. Implemented `PFMERGE` command +15. Implemented `JSON.FORGET` command + +### Features + +1. Added support for arm64 architecture +2. Implemented LFU cache with approximate counting +3. Added config file support +4. Added HTTP support +5. SQL Executor Performance Improvements +6. Added Darwin arm64 compatibility +7. Bumped Go SDK to 1.23 +8. Added minimum and maximum Expiry time + +### Bug Fixes + +1. Fixed auth command line flags to be respected during server startup +2. Fixed `MSET` command consistency issue with Redis +3. Fixed flaky unit test for `JSON` comparisons +4. Fixed flaky `JSON` tests +5. Fixed `GETEX` with `EX` for big integers +6. Fixed TestParseHTTPRequest +7. Fixed `GETKEYS` commands failure for wrong number of arguments + +### Testing + +1. Enhanced `INCR` command test suite with comprehensive edge cases +2. Improved `QWATCH` tests post fingerprinting +3. Enhanced `GETDEL` to handle Set, JSON, ByteArray, String, Integer and expanded test coverage +4. Improved test folder structure +5. Added test for abort command + +### Other + +1. `PFCOUNT` benchmark and caching implementation analysis +2. Updated CONTRIBUTING.md +3. ted report_command_bug.md +4. Reverted change to launch new goroutine for each mutate notification + +# Action Items + +1. Return query fingerprint to users subscribing to QWATCH. +2. Allow unsubscriptions using QWATCH by passing the query fingerprint. +3. Add documentation for QUNWATCH diff --git a/docs/src/content/updates/2024-09-26.md b/docs/src/content/updates/2024-09-26.md new file mode 100644 index 000000000..201a51cdc --- /dev/null +++ b/docs/src/content/updates/2024-09-26.md @@ -0,0 +1,54 @@ +--- +--- + +## Changelog + +New Commands: + +1. Added support for `QWATCH` Command with HTTP (Prashant Shubham) +2. Implemented `HSETNX` command (shreyas23sk) +3. Added support for `INCRBY` command (Saubhik Kumar) +4. Added support for `JSON.OBJKEYS` (Saubhik Kumar) +5. Added support for `JSON.ARRINSERT` (jujiale) +6. Implemented `HDEL` command (manishrw) +7. Added support for `COMMAND INFO` command (meetghodasara) +8. Added support for `HSTRLEN` command (c-harish) +9. Added support for `INCRBYFLOAT` command (hash-f) +10. Added support for `SETEX` command (AshikBN) +11. Added support for `GETRANGE` command (KaviiSuri) +12. Added support for `JSON.NUMMULTBY` (c-harish) +13. Added `ECHO` command (hgupta12) + +Features: + +1. Added multi-threading capability to DiceDB (soumya-codes) +2. Enhanced support for commands over HTTP (Pratik Pandey) +3. Added flag to enable/disable multi-threading on server (Prashant Shubham) +4. Setup slog with zerolog (KaviiSuri) + +Bug Fixes: + +1. Fixed `EXPIRE` with empty string as `TTL` (Abh-ay) +2. Fixed `BITCOUNT` when no key provided (Shardul Silswal) +3. Fixed startup statement (Ashwin Kulkarni) +4. Fixed inconsistent `BITOP` with non-string source key (Karan Dixit) +5. Fixed bitcount operations (Ved Chitnis) +6. Fixed handling of multiple failure/error scenarios during socket reads (ayushsatyam146) +7. Fixed inconsistency in the `INCR` command (Maveric-k07) +8. Fixed keyspacestats and `FLUSHDB` (apoorvyadav1111) +9. Fixed `GETEX` command returning value for JSON-based object (Kapish Malik) +10. Fixed incorrect logging when default port is already in use (Shardul Silswal) + +Testing and Documentation: + +1. Updated README for Multithreading (Prashant Shubham) +2. Added more tests for HTTP support (Pratik Pandey) +3. Added integration tests to validate args for `BITCOUNT` (Shardul Silswal) +4. Added integration tests for HTTP, `ABORT` support for HTTP (Pratik Pandey) + +Other: + +1. Reverted dice binary checked in and added it to .gitignore (Prashant Shubham) +2. Updated README.md (Arpit Bhayani) +3. Eval refactoring for multithreading (Ashwin Kulkarni) +4. Version patch and bump to 0.0.4 (Arpit Bhayani, Jyotinder Singh) diff --git a/docs/src/content/updates/2024-10-03.md b/docs/src/content/updates/2024-10-03.md new file mode 100644 index 000000000..f51b92498 --- /dev/null +++ b/docs/src/content/updates/2024-10-03.md @@ -0,0 +1,84 @@ +--- +--- + +## Changelog + +### New Commands and Features + +1. Added support for `DUMP` command (TheRanomial) +2. Added support for `HKEYS` command (swarajrb7) +3. Added support for `HEXISTS` command (c-harish) +4. Added `JSON.RESP` Command (prateek.singh.rathore) +5. Added support for `JSON.ARRTRIM` (jujiale) +6. Added `HINCRBYFLOAT` command (ayushsatyam146) +7. Added `ZADD` and `ZRANGE` commands (Jyotinder Singh) +8. Added `HINCRBY` Command (ankkyprasad) +9. Added `HVALS` command (bijuli74) +10. Added `HRANDFIELD` command (Indranil0603) +11. Added `APPEND` Command (Aditya-Bhalerao) + +### Improvements and Refactoring + +1. Abstracted out Table implementation and supporting Swiss and Go maps (Arpit Bhayani) +2. Eval Refactor for better compatibility with all protocols and multithreading (Ashwin Kulkarni) +3. Made DiceDB build work on different architectures (swaingotnochill) +4. Added Websocket support (prateek.singh.rathore) +5. Improved code structure for evalHVALS (Jyotinder Singh) + +### Bug Fixes + +1. Fixed `BITPOS` command (Bhavya Jain) +2. Fixed `TYPE` command return encoding (apoorvyadav1111) +3. Fixed Child Process not working for `BGREWRITEAOF` on MacOS (KaviiSuri) + +### Testing and Documentation + +1. Added integration tests for `KEYS`, `MGET` , `MSET`, `JSON` commands using HTTP (Shubh1815) +2. Added HTTP Integration Tests for various commands (Karan Dixit, HARSH VARDHAN SINGH, apoorvyadav1111) +3. Added Websocket integration tests for `SET` and `GET` (prateek.singh.rathore) +4. Updated documentation for various commands (multiple contributors) +5. Improved consistency in documentation for multiple commands (multiple contributors) + +### Other + +1. Made keystat localized to store instance (soumya-codes) +2. Added check for controlling the max TCP connections (Ayush Saluja) +3. Updated README with various improvements (Arpit Bhayani, Dhroov Gupta) +4. Version patch and updates (Arpit Bhayani) + +## Discussion + +Points to discuss \[from Arpit\] + +- Playground mono +- Let’s use the word DiceDB and not Dice, every where, there are variable and config places where the word Dice is used +- The config “REQUEST_LIMIT” should be “REQUEST_LIMIT_PER_MIN” +- The config “REQUEST_WINDOW” should be “REQUEST_WINDOW_SEC” +- What is the purpose of the package internals/cmds? +- Why is there a package called db that just is a wrapper over DiceDB commands? Supporting a new command in Playground now means making a change in both backend and frontend. Also, these functions are essentially useless now. +- Also, A better way would be for SDK to expose a generic command that takes command and argos and executes the. What do you think? +- With this, the need for diced.go vanishes +- Instead of exposing the endpoint as \`/cli\`, let’s call it \`/shell/exec\` +- We need all errors to be standardized w.r.t casing. I propose everything to be lowercase. +- server/httpServer.go \-\> server/http.go, why again the word “server” +- “errorResponse” function should do JSON marshal and not string format +- I see places where log and slog both being used, let’s just use slog everywhere +- Need to understand pkg/util/helpers.go, neither the name not the function made much sense. +- Playground Web +- Have a .env file that can take playground mono URL which points to API URL +- Do not call it \`CLI_COMMAND_URL\`, a bad name. Call it \`PLAYGROUND_MONO_URL\` +- Should we not check in package-lock.json? When I installed the file, it got modified +- README lacks node version requirement +- Does this output static site or does it require a server to run? I see the command \`npm run start\` to start the server in production. Ideally, we want a static website for the playground web. No servers. +- Why is Dockerfile_Backend file even present in web? Also, very bad name. We are calling it Playground Mono. Also, the name is neither snake nor camel case. +- “CLI” is a bad name, let’s call it Shell. +- “ // comment this to hide footer” is such a useless comment. +- Comments are supposed to be \`// comment\` and not \`//comment\` +- “DiceDB PlayGround” as name should be “DiceDB Logo” “Playground” +- “Cleanup in :” and “Command left:” have inconsistent styling. Also, it should be \`Commands left\`. Add a tool tip (i) button, next to both that tells what these limits are all about. +- Move commands from command.ts file to using DiceDB commands command +- Delete mock data file +- In api.ts, propagate the error to the use instead of just logging it to console. Show user the error that was emitted from the backend/mono. +- Constants file may not be required rightnow, given we should use Playground Mono URL from .env +- Instead of calling “blacklist” let’s use the word “blocklist” +- Why cliUtils has get and set and delete, do we not support any other command? Also, given this file is present in utils folder it should be called \`utils/cli.ts\` and not \`utils/cliUtils.ts\` diff --git a/docs/src/content/updates/2024-10-10.md b/docs/src/content/updates/2024-10-10.md new file mode 100644 index 000000000..ab1e8d80c --- /dev/null +++ b/docs/src/content/updates/2024-10-10.md @@ -0,0 +1,80 @@ +--- +--- + +### DB + +New Commands and Features: + +1. Added support for ZRANGE.WATCH (Jyotinder Singh) +2. Implemented GET.WATCH command support (Jyotinder Singh) +3. Added support for HMSET (Raghav Babbar) +4. Implemented GEOADD and GEODIST commands (KaviiSuri) +5. Added support for BITFIELD command with all subcommands (apoorvyadav1111) +6. Implemented HMGET command (vishnuchandrashekar) +7. Added HSCAN command (manish wadhwani) + +Improvements and Refactoring: + +1. Improved Watch Manager and Store API compatibility (Jyotinder Singh) +2. Refactored to handle Watch command type in the generic flow of command handlers (Ashwin Kulkarni) +3. Added query fingerprinting feature (kakdeykaushik) +4. Allowed users to customize the KeysLimit value at server start (vpsinghg) +5. Renamed all appropriate variables from Redis to DiceDB (Ashwin Kulkarni) + +Bug Fixes: + +1. Fixed return value in evalPersist function (shashi-sah2003) +2. Fixed Deque-push-output issue (bhima2001) +3. Fixed DELETE command with 0 arguments (Vansh Chopra) +4. Added Hashmap incrementFloatValue overflow check (dograprabhav) +5. Fixed SINTER to support single key parameter (arushi-08) + +Testing and Documentation: + +1. Added GET.WATCH integration test using SDK (Jyotinder Singh) +2. Added Integration Tests for QWATCH Where Clause (prateek.singh.rathore) +3. Added HTTP integration tests for various commands (Harshit Gupta) +4. Updated documentation for multiple commands (various contributors) +5. Added default config file to be used when dice server starts (Prashant Shubham) + +Performance and Optimization: + +1. Updated JSON.ARRLEN to match RedisCLI outputs (Surya Teja) +2. Marshalling the value in SET command for HTTP (lovish2525) + +Other: + +1. Updated benchmark numbers as of 10th Oct 2024 (Arpit Bhayani) +2. Upgraded vulnerable packages (Progyan) +3. Added support for getting adhocReqChan buffer from config (Rohan Chavan) +4. Changed Github workflow to not run actions for docs related PRs (suryavirkapur) + +### Playground + +#### Playground-web contributions + +1. Render commands with newline char (Tarun) +2. Add tooltip component (Rishabh Gupta) +3. Refactor: monorepo alloy (KaviiSuri) +4. fix: code organisation and rendering (KaviiSuri) +5. Update env vars for Playground Mono and add webservice (Tarun Kantiwal) +6. Cleanup & Adjustment to support static site generation (N3XT) +7. \[Dx\] added pre-commit hooks (Shubham raj) +8. Adding support for generic command execution (Prashant Shubham) +9. Refactor repo for consistency (RishabhC-137) +10. UX Refactor \- 2 (Sarthak Kimtani) +11. Search box scroll added (Aryan Nagbanshi)Updated the Playground mono url endpoint (rishav vajpayee) +12. Enhance command history in CLI (Prathamesh Koshti) +13. Jest testing setup (Prathamesh Koshti) +14. Add prettier for lint and Github workflow (samanyu) + +#### Playground mono contributions + +1. Integration Test for Hash commands (Anish Koulgi) +2. Adding rate limiting headers to responses (ayushsatyam146) +3. Disable list of commands from playground repositories \#897 \- Commands Blacklisted (Yash Budhia) +4. Adding support for generic command execution (Prashant Shubham) +5. Refactored repo for consistency (rishav vajpayee) +6. Add trailing slash middleware to prevent unexpected API crash (Tarun Kantiwal) +7. Integration and stress tests for ratelimiter +8. Added CORS support to server (rishav vajpayee) diff --git a/docs/src/content/updates/2024-10-17.md b/docs/src/content/updates/2024-10-17.md new file mode 100644 index 000000000..240469454 --- /dev/null +++ b/docs/src/content/updates/2024-10-17.md @@ -0,0 +1,65 @@ +--- +--- + +## DB + +### New Features and Commands + +1. Renamed `QWATCH` to `Q.WATCH` for consistency (Jyotinder Singh) +2. Added `BITFIELD_RO` command (Saubhik Kumar) +3. Added support for `OBJECT ENCODING` (Saish Pawar) +4. Added support for command `JSON.STRAPPEND` (Karan Dixit) +5. Migrated `PFADD`, `PFCOUNT`, `PFMERGE` to Multi-threaded architecture (Surya Teja) +6. Migrated `ZADD` and `ZRANGE` commands to multi-threaded architecture (Benjamin Mishra) + +### Improvements and Refactoring + +1. Added profiling for DiceDB (Soumya Panigrahi) +2. Improved config with HTTP and websocket properties (Vinit Parekh) +3. Fixed `.WATCH` fingerprinting to generate consistent fingerprints (Jyotinder Singh) +4. Updated SDK and added tests for `.WATCH` command using new APIs (Jyotinder Singh) +5. Migrated `JSON.CLEAR`, `JSON.STRLRN`, `JSON.OBJLEN` commands (jujiale) + +### Bug Fixes + +1. Fixed `JSON.STRLEN` for no path and type error cases (bhima2001) +2. Fixed handling of multiple failure/error scenarios during socket writes (ayushsatyam146) +3. Fixed HTTP JSON response to use JSON null (Vinit Parekh) +4. Fixed null value in removing array element (Dhroov Gupta) +5. Fixed `JSON.GET` to return error when JSON path does not exist (Samarpan Harit) +6. Refactored evalAPPEND to handle leading zeros in value (Shashi sah) + +### Testing and Documentation + +1. Added more tests for SET command (prateek.singh.rathore) +2. Added HTTP Integration tests for `COMMAND` and `COMMAND/COUNT` (svkaizoku) +3. ted documentation for multiple commands (various contributors) +4. Added common spelling fixes (Abhijeet Kasurde) +5. Optimized README for clipboard copy action (Aditya Poddar) + +### Other + +1. Added Ping telemetry and streamlined Version (Arpit Bhayani) +2. Made error statements similar to Redis in migrated errors (Ashwin Kulkarni) +3. Updated stars on docs (Apoorv Yadav) +4. Switched logging mode to dev by default (KaviiSuri) + +## playground-mono + +1. Add integration tests for SET commands (Dhroov Gupta) +2. Expose ratelimit headers (aasifkhan7) +3. Add Dice command integration tests (EXISTS, EXPIRE, EXPIREAT, EXPIRETIME) and package for validation (Rishabh Gupta) +4. Adding support for pretty response (pshubham) +5. Integration Test for Hash commands (anishkoulgi) +6. Adding support for rendering list based responses (tarun-kavipurapu) + +## playground-web + +1. Adding support for JSON.SET command (pshubham) +2. Unit tests for playground-web repository (ViragJain) +3. fix: docker compose contexts to ensure docker compose runs (Kavii) +4. fix: docker compose contexts to ensure docker compose runs (Kavii) +5. \[DiceDB Console\] Setup NextJS with Electron (Ajay Poshak) +6. Setup NextJS with Electron (Ajay Poshak) +7. Add external links to footer items (pshubham) +8. Fixed the styling of get started button (Aryan Nagbanshi) diff --git a/docs/src/content/updates/2024-10-24.md b/docs/src/content/updates/2024-10-24.md new file mode 100644 index 000000000..917eeae43 --- /dev/null +++ b/docs/src/content/updates/2024-10-24.md @@ -0,0 +1,59 @@ +--- +--- + +## DB + +### New Features + +1. Migrated commands `HLEN`, `HSTRLEN`, and `HSCAN` with integration tests for HTTP, WebSocket, and RESP. (@c-harish, @ashwin-kulkarni128) (\#1024) +2. Added support for `ZPOPMIN` command. (@teja8551) (\#1128) +3. Implemented multi-shard commands: `RENAME`, `COPY` , `MSET`, and `MGET`. (@ashwin-kulkarni128) (\#1059) +4. Bloom Filter Commands: Migrated commands such as `bf.add`, `bf.reserve`, `bf.exists`, and `bf.info` to store_eval. (@apoorvyadav1111) (\#1031) +5. Added support for command `ZRANK`. (@SyedMa3) (\#1126) + +### Enhancements + +1. Migrated INCR commands and added integration tests for WebSocket. (@pg30) (\#1016) +2. Migrated commands `HINCRBY`, `HINCRBYFLOAT`, and `HRANDFIELD` with refactored cmdmeta and eval logic. (@saisaipawar, @ashwin-kulkarni128) (\#1081) +3. Moved supported protocols under Protocols. (@arpitbhayani) +4. Added CLI example to WebSocket documentation. (@JP-sDEV) (\#1113) + +### Bug Fixes + +1. Fixed issues in specific use cases of `ZPOPMIN` command. (@teja8551) (\#1164) +2. Handled root path '.' correctly in `JSON.OBJLEN` command. (@saubhikpandey) (\#603) +3. Fixed `ZRANK` command to return score as string with `WITHSCORE`. (@shashi-sah2003) (\#1165) +4. Fixed bugs in WebSocket integration tests. (@psr) (\#1142) + +### Documentation Updates + +1. Audited and enhanced documentation for the `COPY` command. (@onlybond) (\#816) +2. Added Hello, World examples for Simple and Reactive protocols. (@arpitbhayani) +3. Added documentation for Reactive Hello, World\! (@arpitbhayani) +4. Enhanced documentation for the sleep command. (@kdivyansh268, @pshubham) (\#832) +5. Audited `Q.WATCH` documentation for consistency. (@shashank-priyadarshi) (\#781) +6. Updated `INCR` command documentation for consistency with Redis. (@pg30) +7. Audited documentation for the `JSON.TYPE` command. (@onlybond) (\#827) +8. Added cURL examples to HTTP documentation. (@vanshavenger) (\#1113) + +### Refactoring + +1. Refactored HyperLogLog command responses and removed logger references. (@prashant1996cr07) (\#1183) +2. Refactored HTTP response structure. (@prashant1996cr07) (\#1150) + +### Logging and Configuration + +1. Made logging consistent across start and shutdown sequences. (@arpitbhayani) (\#1172) +2. Added an option to set default log level to info. (@arpitbhayani) (\#1172) +3. Configured the number of shards as a configuration, defaulting to the number of cores. (@arpitbhayani) (\#1172) +4. Set connection close log level to debug. (@soumya-codes) (\#1139) + +### Miscellaneous + +1. Updated README.md with new CLI instructions. (@arpitbhayani) +2. Linked and documented best practices for contributions and logging. (@arpitbhayani) +3. Added DiceDB ASCII art for CLI. (@arpitbhayani) +4. Added a template for command documentation. (@apoorvyadav1111) (\#1147) +5. Removed unnecessary log references. (@prashant1996cr07) +6. Removed multi-threading experimental mode from the README. (@arpitbhayani) +7. Version bump to 0.0.5. (@arpitbhayani) diff --git a/docs/src/content/updates/2024-11-07.md b/docs/src/content/updates/2024-11-07.md new file mode 100644 index 000000000..a921f7c6a --- /dev/null +++ b/docs/src/content/updates/2024-11-07.md @@ -0,0 +1,35 @@ +--- +--- + +## DB + +### New Features + +- Migrate commands `SADD`, `SREM`, `SCARD`, `SMEMBERS` to store_eval. (@sahoss) (\#1020) +- Add support for commands `LINSERT` and `LRANGE`. (@ParvBudh28) (\#659) +- Add integration tests for commands `HSET`, `HGET`, `HDEL`. (@c-harish) (\#1021) +- Migrate `GETEX` and `GETDEL` commands. (@Ehijoe) (\#1061) +- Migrated commands `EXPIRE`, `EXPIREAT`, `EXPIRETIME`, `TTL`, `PTTL`. (@SyedMa3) (\#1149) +- Added `GET.UNWATCH` command support and fixed related issues. (@psr) (\#998) + +### Enhancements + +- ZPOPMIN command tests enhanced to check outputs with ZCOUNT command. (@teja8551) (\#1225) +- Moved HExists, HKeys, HVals commands in commands folder. (@apoorvyadav1111) (\#1229) + +### Fixes + +- Fix typo in documentation. (@vinitparekh1742) (\#1240) +- Fix `validateCmdMeta` to handle Unwatch commands. (@jyotindrsingh) + +### Documentation Updates + +- Revamped documentation with separate sections for Blog, Benchmarks, and Roadmap. (@arpitbhayani) (\#1236) +- Add support for command SELECT documentation. (@vanshavenger) (\#820) +- Add documentation for `LINSERT` and `LRANGE` commands. (@ParvBudh28) (\#1040) +- Release page added with blogs and release notes on the homepage. (@arpitbhayani) +- Lint across docs codebase. (@arpitbhayani) +- Removed memtier benchmark from Docs. (@arpitbhayani) +- Updated benchmark numbers and Redis compatibility page. (@arpitbhayani) +- Made landing page simpler and denser. (@arpitbhayani) +- Code documentation fixes. (@aadi-1024) (\#1232) diff --git a/docs/src/content/updates/2024-11-14.md b/docs/src/content/updates/2024-11-14.md new file mode 100644 index 000000000..ec3c925e2 --- /dev/null +++ b/docs/src/content/updates/2024-11-14.md @@ -0,0 +1,29 @@ +--- +--- + +## DB + +### New Features + +- Migrated JSON.RESP & JSON.DEBUG commands. (@c-harish) (\#1030) +- Migrated LPUSH, RPUSH, LPOP, RPOP, LLEN commands. (@Aditya-Chowdhary) (\#1019) +- Implemented ZADD options: XX, NX, CH, INCR, LT, GT according to Redis source. (@rushabhk04) (\#761) +- Migrate commands SETBIT, GETBIT, BITCOUNT, BITPOS, BITFIELD, BITFIELD_RO. (@vishnuchandrashekar) (\#1017) +- Added support for PFCOUNT.WATCH command. (@saubhikpandey) (\#1133) +- Command migration for single shard, multi-shard, and custom commands. (@ashwin-kulkarni128, @apoorvyadav1111) (\#1276) +- Refactored eviction framework with Basic LRU-based batch eviction. (@soumya-codes) (\#1268) +- Default WAL set to Null with WAL implementation added. (@arpitbhayani) + +### Bug Fixes + +- Fixed RESP parser to parse strings with multiple `\r`. (@c-harish) (\#1245) +- Fix LPOP to support multiple arguments. (@tren03) (\#1100) +- Added command metadata for LRANGE. (@shashi-sah2003) (\#1272) +- Enhanced GETRANGE to support byte array. (@c-harish) (\#1194) +- Added type check for string compatibility in evalAPPEND function. (@shashi-sah2003) (\#1193) + +### Documentation Updates + +- Reactive value proposition added to documentation. (@arpitbhayani) (\#1256) +- Releases page with blogs and release notes on the homepage. (@arpitbhayani) +- Roadmap and Redis compatibility page updated. (@arpitbhayani) diff --git a/docs/src/content/updates/2024-11-21.md b/docs/src/content/updates/2024-11-21.md new file mode 100644 index 000000000..9ab560688 --- /dev/null +++ b/docs/src/content/updates/2024-11-21.md @@ -0,0 +1,44 @@ +--- +--- + +## DB + +### New Features + +- Add support for `PFCOUNT.UNWATCH` command and cleanup reactivity tests. (@jyotindrsingh) (\#1030) +- Preserve `TTL` after `APPEND` command. (@dhanrajkotian3) (\#1036) +- Command migration for multishard commands: `TOUCH`, `DBSIZE`, `KEYS`. (@ashwin-kulkarni128, @jyotindrsingh) (\#1301) +- Migrated `GEOADD` and `GEODIST` commands. (@ygosain44) (\#1033) +- Add support for byte array/bitmap to APPEND command. (@c-harish) (\#1286) + +### Enhancements + +- Fix enable-multithreading flag and `PING` support. (@jyotindrsingh) +- Added labels for `WATCH` commands. (@psr) (\#1267) +- Refactored configuration management to use a `.conf` file. (@vinitparekh1742) (\#1292) +- Refactored `IOHandler` code. (@soumya-codes) (\#1306) +- Added `ZADD` documentation and improved error messages. (@vanshavenger) (\#1283) + +### Bug Fixes + +- Fixed goroutine leaks and deadlocks in worker and RESP integration tests. (@psr) (\#1298) +- Fix typo in `benchmarks.md`. (@vinitparekh1742) +- Ensure CI runs only when source code has changes. (@bhima2001) (\#1260) + +### Documentation Updates + +- Updated package-lock. (@apoorvyadav1111) (\#1311) +- Added documentation for new watch/unwatch commands. (@apoorvyadav1111) (\#1295) +- Changes in README for new configuration. (@vinitparekh1742) (\#1309) +- Added type documentation. (@vanshavenger) (\#1280) +- Reactivity page and quick write-up added. (@arpitbhayani) (\#1308) + +### Refactoring + +- Refactored Makefile. (@vinitparekh1742) (\#1288) +- Fixed CI and linting issues across codebase. (@arpitbhayani, @jyotindrsingh) + +### Miscellaneous + +- Consistent blog card styling on the website. (@realChakrawarti) (\#1300) +- Set up a `/docs` redirect. (@arpitbhayani) diff --git a/docs/src/content/updates/2024-11-28.md b/docs/src/content/updates/2024-11-28.md new file mode 100644 index 000000000..920c8e64c --- /dev/null +++ b/docs/src/content/updates/2024-11-28.md @@ -0,0 +1,48 @@ +--- +--- + +## DB + +### New Features + +- Command Migration: Migrated `DEL`, `EXISTS`, `PERSIST`, and `TYPE` commands.\*\* (@mohitnagaraj20, @jyotindrsingh, @apoorvyadav1111) (\#1015) +- Added support for PFCOUNT.UNWATCH command. (@jyotindrsingh) (\#1335) +- Integration tests added for COMMAND DOCS command. (@sa-k-shore) (\#1323) + +### Enhancements + +- Preserve TTL after APPEND command. (@dhanrajkotian3) (\#1036) +- Refactored configuration management to improve flag handling and introduce early returns for errors. (@jyotindrsingh) +- Rounded borders, word wrap, and badges added for improved UI. (@apoorvyadav1111) (\#1327) +- Reorganized IOThread code and added IOThread interface to BaseIOThread. (@jyotindrsingh) (\#1331) +- Cleaned up startup logs. (@jyotindrsingh) (\#1316) +- Removed async server. (@ashwin-kulkarni128, @jyotindrsingh, @apoorvyadav1111) (\#1318) +- Fixed Redis CLI connection error. (@prashant1996cr07) (\#1207) + +### Bug Fixes + +- Fixed configuration flags for better compatibility. (@jyotindrsingh) (\#1331) +- Fix Redis CLI connect error. (@prashant1996cr07) (\#1207) +- Fix to ensure fingerprints are retained until all clients unsubscribe. (@prashant1996cr07) (\#1335) +- Fixed linter issues across multiple files. (@jyotindrsingh, @apoorvyadav1111) (\#1314, \#1333) +- Removed unused utilities and dead code. (@jyotindrsingh) (\#1331) +- Fix for `GETRANGE` markdown file extension detection. (@Arijit6258) (\#1329) + +### Documentation Updates + +- Added links to examples in documentation. (@apoorvyadav1111) (\#1333) +- Temporarily removed `Q.WATCH` documentation from the website. (@jyotindrsingh) (\#1334) +- Updated documentation with improved clarity and layout. (@vinitparekh1742, @jyotindrsingh) (\#1332) +- Added hyperlinks for commands. (@pankajshadev) (\#1325) + +### Refactoring + +- Makefile updates for consistency. (@vinitparekh1742) (\#1310) +- Removed cache from linter for better performance. (@apoorvyadav1111) (\#1319) +- Reorganized and renamed Worker to IOThread. (@jyotindrsingh) (\#1330) + +### Miscellaneous + +- Version bump. (@jyotindrsingh) (\#1316) +- Dependency upgrade: Bumped `golang.org/x/net` from `0.21.0` to `0.23.0`.\*\* (@dependabot\[bot\]) (\#1316) +- Deleted outdated `GETRANGE` documentation. (@c-harish) (\#1338) diff --git a/docs/src/content/updates/2024-12-05.md b/docs/src/content/updates/2024-12-05.md new file mode 100644 index 000000000..68f23b897 --- /dev/null +++ b/docs/src/content/updates/2024-12-05.md @@ -0,0 +1,21 @@ +--- +--- + +### New Features + +- Bloom Filter and Type Standardization: This PR introduces bloom filter and type standardization to improve performance (@arpitbbhayani) (\#1357) +- Add documentation for SETEX command: Added documentation for the SETEX command, making it easier for users to understand its usage (@tarun-29) (\#1350) + +### Bug Fixes + +- Fixed build error in bytearray.go: This PR fixes a build error that occurred when building the bytearray package (@piyushhhxyz) (\#1351) +- fix: modify the config default value keep consistency: This PR standardizes the default values of configuration options across the codebase, ensuring consistency and preventing potential issues (@jujiale) (\#1352) + +### Documentation + +- Add documentation for JSON.OBJLEN command: Created a new page in the documentation for the JSON.OBJLEN command, while also fixing typos on the JSON.OBJKEYS page (@paulwalrath) (\#1345) +- Remove \--enable-multithreading flag usage in README: Removed the reference to the deprecated \`--enable-multithreading\` flag from the README, as it is no longer supported (@rahul-mallick-15) (\#1349) + +### General Enhancements + +- Remove encoding and supporting only Type: This PR removes unused encoding code and supports only type (@arpitbbhayani) (\#1341) diff --git a/docs/src/layouts/BlogLayout.astro b/docs/src/layouts/BlogLayout.astro index f2222fb0c..5644e69aa 100644 --- a/docs/src/layouts/BlogLayout.astro +++ b/docs/src/layouts/BlogLayout.astro @@ -4,7 +4,11 @@ import Layout from "./Layout.astro"; import AboutMeVertical from "../components/AboutMeVertical.astro"; const { blog, type } = Astro.props; -const author = await getEntry("authors", blog.data.author.id); +let author = null; + +if (blog?.data?.author?.id) { + author = await getEntry("authors", blog.data.author.id); +} const JSONLD = { "@context": "https://schema.org/", @@ -18,8 +22,8 @@ const JSONLD = { dateModified: blog.data.published_at, author: { "@type": "Person", - name: author.data.name, - image: author.data.avatar_url, + name: author?.data?.name, + image: author?.data?.avatar_url, }, url: Astro.url, isPartOf: { @@ -28,8 +32,8 @@ const JSONLD = { name: "DiceDB Blog", publisher: { "@type": "Person", - name: author.data.name, - image: author.data.avatar_url, + name: author?.data?.name, + image: author?.data?.avatar_url, }, }, }; @@ -51,6 +55,13 @@ const JSONLD = {
  • Releases
  • + ) : type === "update" ? ( +
  • + Weekly Updates +
  • +
  • + {blog.slug} +
  • ) : (
  • Blog @@ -68,35 +79,39 @@ const JSONLD = { > {blog.data.title} -
    -
    -
    - -
    -
    -
    -

    - {author.data.name} -

    -

    - {author.data.bio} -

    -
    -
    + { + author && ( +
    +
    +
    + +
    +
    +
    +

    + + {author.data.name} + +

    +

    {author.data.bio}

    +
    +
    + ) + }

  • -

    - { - blog.data.published_at.toLocaleString("en-us", { - day: "2-digit", - month: "short", - year: "numeric", - }) - } -

    + { + type !== "update" && ( +

    + {blog.data.published_at.toLocaleString("en-us", { + day: "2-digit", + month: "short", + year: "numeric", + })} +

    + ) + }
    diff --git a/docs/src/layouts/Head.astro b/docs/src/layouts/Head.astro index 0c4c7263f..c379a8c71 100644 --- a/docs/src/layouts/Head.astro +++ b/docs/src/layouts/Head.astro @@ -14,6 +14,5 @@ const { title, description, img, blog, video, session, JSONLD } = Astro.props; {title} - diff --git a/docs/src/pages/community/index.astro b/docs/src/pages/community/index.astro new file mode 100644 index 000000000..588b386c5 --- /dev/null +++ b/docs/src/pages/community/index.astro @@ -0,0 +1,69 @@ +--- +import Layout from "../../layouts/Layout.astro"; +import { getCollection } from "astro:content"; +import { Video } from "lucide-astro"; + +const updates = await getCollection("updates"); +updates.reverse(); + +const title = "Community"; +const description = ""; +const callLink = "https://meet.google.com/qdf-pfkb-ckm"; +--- + + +
    +
    +

    Community

    +

    + DiceDB is a community-driven project, and every individual who has + contributed their time, expertise, and patches has played a crucial role + in shaping its success. If you're interested in contributing to DiceDB, + you can always +

    + The community is always open to new ideas and contributions, so feel free + to drop a note on our Discord server. +

    +
    +

    Weekly calls

    +

    + We need every Thursday at 19:00 IST to discuss what we did and what we + plan to do. The meeting is open to everyone, and you can join the call + by clicking the button below. +

    + +
    +

    Here are the notes from our past weekly calls

    +
    + +
    +
    +
    +
    diff --git a/docs/src/pages/team.astro b/docs/src/pages/team.astro new file mode 100644 index 000000000..a2df83d4e --- /dev/null +++ b/docs/src/pages/team.astro @@ -0,0 +1,122 @@ +--- +import Layout from "../layouts/Layout.astro"; +import { getCollection } from "astro:content"; +import UserSocialHandles from "../components/UserSocialHandles.astro"; +const team = await getCollection("team"); + +const pmc = team.filter((member) => member.data.roles.includes("pmc")); +const committers = team.filter((member) => + member.data.roles.includes("committer"), +); + +const title = "Team"; +const description = + "DiceDB is a community-driven project, and every individual who has contributed their time, expertise, and patches has played a crucial role in shaping its success."; +--- + + +
    +
    +

    Team

    +

    + DiceDB is a community-driven project, and every individual who has + contributed their time, expertise, and patches has played a crucial role + in shaping its success. Our team is organized into three key groups: +

      +
    • Project Management Committee (PMC)
    • +
    • Committers
    • +
    • Contributors
    • +
    +

    +
    +

    Project Management Committee

    +

    + Our Project Management Committee (PMC) steers the vision, ensuring + DiceDB stays aligned with its mission of building a reactive, scalable, + highly available, unified cache optimized for modern hardware. +

    +
    +
    + { + pmc.map((member) => ( +
    + {member.data.name} +

    + {member.data.name.split(" ").map((char) => ( +
    {char}
    + ))} +

    + +
    + )) + } +
    +
    +

    Committers

    +

    + The committers, with their deep expertise, safeguard the stability and + quality of the codebase along with working on critical features and + improvements. +

    +
    + { + committers.map((member) => ( +
    + {member.data.name} +

    {member.data.name}

    + +
    + )) + } +
    +
    +

    Contributors

    +

    + The contributors, with their fresh ideas and energy, push the boundaries + of what's possible. Each project has its own contributors, and you can + find them below. We regularly evaluate the contributions and promote + contributors to committers. +

    +

    +
    +
    +
    + + diff --git a/docs/src/pages/updates/[slug].astro b/docs/src/pages/updates/[slug].astro new file mode 100644 index 000000000..7fb5498b4 --- /dev/null +++ b/docs/src/pages/updates/[slug].astro @@ -0,0 +1,20 @@ +--- +import { getCollection } from "astro:content"; +import BlogLayout from "../../layouts/BlogLayout.astro"; +export async function getStaticPaths() { + const updates = (await getCollection("updates")).sort( + (a, b) => new Date(b.slug).getTime() - new Date(a.slug).getTime(), + ); + return updates.map((update) => ({ + params: { slug: update.slug }, + props: { update }, + })); +} + +const { update } = Astro.props; +const { Content } = await update.render(); +--- + + + + From af04a489ac9a8905851df56a18f181ccdbb17103 Mon Sep 17 00:00:00 2001 From: Jyotinder Singh Date: Sat, 14 Dec 2024 22:00:22 +0530 Subject: [PATCH 18/25] Switches license to GNU AGPL 3.0 (#1372) --- config/config.go | 16 ++++++++++++++++ config/parser.go | 16 ++++++++++++++++ config/validator.go | 16 ++++++++++++++++ examples/leaderboard-go/main.go | 16 ++++++++++++++++ examples/url-shortener/main.go | 16 ++++++++++++++++ integration_tests/commands/http/append_test.go | 16 ++++++++++++++++ integration_tests/commands/http/bit_test.go | 16 ++++++++++++++++ integration_tests/commands/http/bloom_test.go | 16 ++++++++++++++++ .../commands/http/check_type_test.go | 16 ++++++++++++++++ .../commands/http/command_count_test.go | 16 ++++++++++++++++ .../commands/http/command_default_test.go | 16 ++++++++++++++++ .../commands/http/command_docs_test.go | 16 ++++++++++++++++ .../commands/http/command_getkeys_test.go | 16 ++++++++++++++++ .../commands/http/command_help_test.go | 16 ++++++++++++++++ .../commands/http/command_info_test.go | 16 ++++++++++++++++ .../commands/http/command_list_test.go | 16 ++++++++++++++++ .../commands/http/command_rename_test.go | 16 ++++++++++++++++ integration_tests/commands/http/copy_test.go | 16 ++++++++++++++++ .../commands/http/countminsketch_test.go | 16 ++++++++++++++++ integration_tests/commands/http/dbsize_test.go | 16 ++++++++++++++++ integration_tests/commands/http/decr_test.go | 16 ++++++++++++++++ integration_tests/commands/http/del_test.go | 16 ++++++++++++++++ integration_tests/commands/http/deque_test.go | 16 ++++++++++++++++ integration_tests/commands/http/echo_test.go | 16 ++++++++++++++++ integration_tests/commands/http/exists_test.go | 16 ++++++++++++++++ integration_tests/commands/http/expire_test.go | 16 ++++++++++++++++ integration_tests/commands/http/expireat_test.go | 16 ++++++++++++++++ .../commands/http/expiretime_test.go | 16 ++++++++++++++++ integration_tests/commands/http/geo_test.go | 16 ++++++++++++++++ integration_tests/commands/http/get_test.go | 16 ++++++++++++++++ integration_tests/commands/http/getdel_test.go | 16 ++++++++++++++++ integration_tests/commands/http/getex_test.go | 16 ++++++++++++++++ integration_tests/commands/http/getrange_test.go | 16 ++++++++++++++++ integration_tests/commands/http/getset_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hdel_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hexists_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hget_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hincrby_test.go | 16 ++++++++++++++++ .../commands/http/hincrbyfloat_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hkeys_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hlen_test.go | 16 ++++++++++++++++ .../commands/http/hrandfield_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hscan_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hset_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hsetnx_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hstrlen_test.go | 16 ++++++++++++++++ integration_tests/commands/http/hvals_test.go | 16 ++++++++++++++++ .../commands/http/hyperloglog_test.go | 16 ++++++++++++++++ .../commands/http/incr_by_float_test.go | 16 ++++++++++++++++ integration_tests/commands/http/incr_test.go | 16 ++++++++++++++++ .../commands/http/json_arrpop_test.go | 16 ++++++++++++++++ integration_tests/commands/http/json_test.go | 16 ++++++++++++++++ .../commands/http/jsondebug_test.go | 16 ++++++++++++++++ integration_tests/commands/http/jsonresp_test.go | 16 ++++++++++++++++ integration_tests/commands/http/keys_test.go | 16 ++++++++++++++++ integration_tests/commands/http/main_test.go | 16 ++++++++++++++++ integration_tests/commands/http/mget_test.go | 16 ++++++++++++++++ integration_tests/commands/http/mset_test.go | 16 ++++++++++++++++ integration_tests/commands/http/object_test.go | 16 ++++++++++++++++ .../commands/http/set_data_cmd_test.go | 16 ++++++++++++++++ integration_tests/commands/http/set_test.go | 16 ++++++++++++++++ integration_tests/commands/http/setup.go | 16 ++++++++++++++++ integration_tests/commands/http/touch_test.go | 16 ++++++++++++++++ integration_tests/commands/http/ttl_pttl_test.go | 16 ++++++++++++++++ integration_tests/commands/http/type_test.go | 16 ++++++++++++++++ integration_tests/commands/http/zcard_test.go | 16 ++++++++++++++++ integration_tests/commands/http/zpopmax_test.go | 16 ++++++++++++++++ integration_tests/commands/http/zrank_test.go | 16 ++++++++++++++++ integration_tests/commands/http/zrem_test.go | 16 ++++++++++++++++ integration_tests/commands/http/zset_test.go | 16 ++++++++++++++++ .../commands/resp/abort/server_abort_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/append_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/bit_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/bloom_test.go | 16 ++++++++++++++++ .../commands/resp/check_type_test.go | 16 ++++++++++++++++ .../commands/resp/command_count_test.go | 16 ++++++++++++++++ .../commands/resp/command_default_test.go | 16 ++++++++++++++++ .../commands/resp/command_docs_test.go | 16 ++++++++++++++++ .../commands/resp/command_getkeys_test.go | 16 ++++++++++++++++ .../commands/resp/command_info_test.go | 16 ++++++++++++++++ .../commands/resp/command_list_test.go | 16 ++++++++++++++++ .../commands/resp/command_rename_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/copy_test.go | 16 ++++++++++++++++ .../commands/resp/countminsketch_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/dbsize_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/decr_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/del_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/deque_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/dump_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/echo_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/exists_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/expire_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/flushdb_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/geo_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/get_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/getdel_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/getex_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/getrange_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/getset_test.go | 16 ++++++++++++++++ .../commands/resp/getunwatch_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/getwatch_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hdel_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hello_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hexists_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hget_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hgetall_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hincrby_test.go | 16 ++++++++++++++++ .../commands/resp/hincrbyfloat_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hkeys_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hlen_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hmget_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hmset_test.go | 16 ++++++++++++++++ .../commands/resp/hrandfield_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hscan_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hset_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hsetnx_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hstrlen_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/hvals_test.go | 16 ++++++++++++++++ .../commands/resp/hyperloglog_test.go | 16 ++++++++++++++++ .../commands/resp/incr_by_float_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/incr_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/json_test.go | 16 ++++++++++++++++ .../commands/resp/jsondebug_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/jsonresp_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/keys_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/main_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/mget_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/mset_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/object_test.go | 16 ++++++++++++++++ .../commands/resp/pfcountwatch_test.go | 16 ++++++++++++++++ .../commands/resp/set_data_cmd_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/set_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/setup.go | 16 ++++++++++++++++ integration_tests/commands/resp/touch_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/ttl_pttl_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/type_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/zcard_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/zpopmax_test.go | 16 ++++++++++++++++ .../commands/resp/zrangewatch_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/zrank_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/zrem_test.go | 16 ++++++++++++++++ integration_tests/commands/resp/zset_test.go | 16 ++++++++++++++++ .../commands/websocket/append_test.go | 16 ++++++++++++++++ integration_tests/commands/websocket/bit_test.go | 16 ++++++++++++++++ .../commands/websocket/bloom_test.go | 16 ++++++++++++++++ .../commands/websocket/command_docs_test.go | 16 ++++++++++++++++ .../commands/websocket/countminsketch_test.go | 16 ++++++++++++++++ .../commands/websocket/decr_test.go | 16 ++++++++++++++++ integration_tests/commands/websocket/del_test.go | 16 ++++++++++++++++ .../commands/websocket/deque_test.go | 16 ++++++++++++++++ .../commands/websocket/exists_test.go | 16 ++++++++++++++++ .../commands/websocket/expire_test.go | 16 ++++++++++++++++ integration_tests/commands/websocket/geo_test.go | 16 ++++++++++++++++ integration_tests/commands/websocket/get_test.go | 16 ++++++++++++++++ .../commands/websocket/getrange_test.go | 16 ++++++++++++++++ .../commands/websocket/hdel_test.go | 16 ++++++++++++++++ integration_tests/commands/websocket/helper.go | 16 ++++++++++++++++ .../commands/websocket/hexists_test.go | 16 ++++++++++++++++ .../commands/websocket/hget_test.go | 16 ++++++++++++++++ .../commands/websocket/hincrby_test.go | 16 ++++++++++++++++ .../commands/websocket/hincrbyfloat_test.go | 16 ++++++++++++++++ .../commands/websocket/hkeys_test.go | 16 ++++++++++++++++ .../commands/websocket/hlen_test.go | 16 ++++++++++++++++ .../commands/websocket/hrandfield_test.go | 16 ++++++++++++++++ .../commands/websocket/hscan_test.go | 16 ++++++++++++++++ .../commands/websocket/hset_test.go | 16 ++++++++++++++++ .../commands/websocket/hstrlen_test.go | 16 ++++++++++++++++ .../commands/websocket/hvals_test.go | 16 ++++++++++++++++ .../commands/websocket/hyperloglog_test.go | 16 ++++++++++++++++ .../commands/websocket/incr_by_float_test.go | 16 ++++++++++++++++ .../commands/websocket/incr_test.go | 16 ++++++++++++++++ .../commands/websocket/json_test.go | 16 ++++++++++++++++ .../commands/websocket/jsondebug_test.go | 16 ++++++++++++++++ .../commands/websocket/jsonresp_test.go | 16 ++++++++++++++++ .../commands/websocket/main_test.go | 16 ++++++++++++++++ integration_tests/commands/websocket/set_test.go | 16 ++++++++++++++++ integration_tests/commands/websocket/setup.go | 16 ++++++++++++++++ .../commands/websocket/ttl_pttl_test.go | 16 ++++++++++++++++ .../commands/websocket/type_test.go | 16 ++++++++++++++++ .../commands/websocket/writeretry_test.go | 16 ++++++++++++++++ .../commands/websocket/zcard_test.go | 16 ++++++++++++++++ .../commands/websocket/zpopmax_test.go | 16 ++++++++++++++++ .../commands/websocket/zrank_test.go | 16 ++++++++++++++++ .../commands/websocket/zrem_test.go | 16 ++++++++++++++++ .../commands/websocket/zset_test.go | 16 ++++++++++++++++ integration_tests/config/config_test.go | 16 ++++++++++++++++ integration_tests/config/parser_test.go | 16 ++++++++++++++++ integration_tests/server/max_conn_test.go | 16 ++++++++++++++++ integration_tests/server/server_abort_test.go | 16 ++++++++++++++++ integration_tests/server/setup.go | 16 ++++++++++++++++ internal/auth/session.go | 16 ++++++++++++++++ internal/auth/session_test.go | 16 ++++++++++++++++ internal/cli/cli.go | 16 ++++++++++++++++ internal/clientio/io.go | 16 ++++++++++++++++ internal/clientio/io_test.go | 16 ++++++++++++++++ internal/clientio/iohandler/iohandler.go | 16 ++++++++++++++++ internal/clientio/iohandler/netconn/netconn.go | 16 ++++++++++++++++ .../iohandler/netconn/netconn_resp_test.go | 16 ++++++++++++++++ .../clientio/iohandler/netconn/netconn_test.go | 16 ++++++++++++++++ internal/clientio/requestparser/parser.go | 16 ++++++++++++++++ .../clientio/requestparser/resp/respparser.go | 16 ++++++++++++++++ .../requestparser/resp/respparser_test.go | 16 ++++++++++++++++ internal/clientio/resp.go | 16 ++++++++++++++++ internal/clientio/resp_test.go | 16 ++++++++++++++++ internal/cmd/cmds.go | 16 ++++++++++++++++ internal/comm/client.go | 16 ++++++++++++++++ internal/common/map.go | 16 ++++++++++++++++ internal/common/regmap.go | 16 ++++++++++++++++ internal/common/swisstable.go | 16 ++++++++++++++++ internal/dencoding/dencoding_benchmark_test.go | 16 ++++++++++++++++ internal/dencoding/int.go | 16 ++++++++++++++++ internal/dencoding/int_test.go | 16 ++++++++++++++++ internal/errors/errors.go | 16 ++++++++++++++++ internal/errors/migrated_errors.go | 16 ++++++++++++++++ internal/eval/bitpos.go | 16 ++++++++++++++++ internal/eval/bloom_test.go | 16 ++++++++++++++++ internal/eval/bloom_utils.go | 16 ++++++++++++++++ internal/eval/bytearray.go | 16 ++++++++++++++++ internal/eval/bytearray_test.go | 16 ++++++++++++++++ internal/eval/bytelist.go | 16 ++++++++++++++++ internal/eval/bytelist_test.go | 16 ++++++++++++++++ internal/eval/commands.go | 16 ++++++++++++++++ internal/eval/constants.go | 16 ++++++++++++++++ internal/eval/countminsketch.go | 16 ++++++++++++++++ internal/eval/countminsketch_test.go | 16 ++++++++++++++++ internal/eval/deque.go | 16 ++++++++++++++++ internal/eval/deque_test.go | 16 ++++++++++++++++ internal/eval/dump_restore.go | 16 ++++++++++++++++ internal/eval/eval.go | 16 ++++++++++++++++ internal/eval/eval_test.go | 16 ++++++++++++++++ internal/eval/execute.go | 16 ++++++++++++++++ internal/eval/geo/geo.go | 16 ++++++++++++++++ internal/eval/hmap.go | 16 ++++++++++++++++ internal/eval/hmap_test.go | 16 ++++++++++++++++ internal/eval/main_test.go | 16 ++++++++++++++++ internal/eval/sortedset/sorted_set.go | 16 ++++++++++++++++ internal/eval/store_eval.go | 16 ++++++++++++++++ internal/eval/type_asserts.go | 16 ++++++++++++++++ internal/eval/type_bloomfilter.go | 16 ++++++++++++++++ internal/eval/type_string.go | 16 ++++++++++++++++ internal/eval/type_string_test.go | 16 ++++++++++++++++ internal/id/id.go | 16 ++++++++++++++++ internal/id/id_test.go | 16 ++++++++++++++++ internal/iomultiplexer/constants.go | 16 ++++++++++++++++ internal/iomultiplexer/epoll_linux.go | 16 ++++++++++++++++ internal/iomultiplexer/errors.go | 16 ++++++++++++++++ internal/iomultiplexer/interface.go | 16 ++++++++++++++++ internal/iomultiplexer/kqueue_darwin.go | 16 ++++++++++++++++ internal/iomultiplexer/types.go | 16 ++++++++++++++++ internal/iomultiplexer/types_darwin.go | 16 ++++++++++++++++ internal/iomultiplexer/types_linux.go | 16 ++++++++++++++++ internal/iothread/cmd_compose.go | 16 ++++++++++++++++ internal/iothread/cmd_custom.go | 16 ++++++++++++++++ internal/iothread/cmd_decompose.go | 16 ++++++++++++++++ internal/iothread/cmd_meta.go | 16 ++++++++++++++++ internal/iothread/cmd_preprocess.go | 16 ++++++++++++++++ internal/iothread/iothread.go | 16 ++++++++++++++++ internal/iothread/manager.go | 16 ++++++++++++++++ internal/logger/logger.go | 16 ++++++++++++++++ internal/logger/zerolog.go | 16 ++++++++++++++++ internal/object/deep_copy.go | 16 ++++++++++++++++ internal/object/object.go | 16 ++++++++++++++++ internal/object/typeencoding.go | 16 ++++++++++++++++ internal/observability/constants.go | 16 ++++++++++++++++ internal/observability/hardware.go | 16 ++++++++++++++++ internal/observability/instance.go | 16 ++++++++++++++++ internal/observability/ping.go | 16 ++++++++++++++++ internal/ops/store_op.go | 16 ++++++++++++++++ internal/querymanager/query_manager.go | 16 ++++++++++++++++ internal/querymanager/watch_response.go | 16 ++++++++++++++++ internal/regex/regex.go | 16 ++++++++++++++++ internal/regex/regex_test.go | 16 ++++++++++++++++ .../server/abstractserver/abstract_server.go | 16 ++++++++++++++++ internal/server/httpws/httpResp.go | 16 ++++++++++++++++ internal/server/httpws/httpServer.go | 16 ++++++++++++++++ internal/server/httpws/redisCmdAdapter.go | 16 ++++++++++++++++ internal/server/httpws/redisCmdAdapter_test.go | 16 ++++++++++++++++ internal/server/httpws/websocketServer.go | 16 ++++++++++++++++ internal/server/resp/server.go | 16 ++++++++++++++++ internal/server/utils/array.go | 16 ++++++++++++++++ internal/server/utils/bitfield.go | 16 ++++++++++++++++ internal/server/utils/boolToInt.go | 16 ++++++++++++++++ internal/server/utils/constants.go | 16 ++++++++++++++++ internal/server/utils/floatToInt.go | 16 ++++++++++++++++ internal/server/utils/json.go | 16 ++++++++++++++++ internal/server/utils/jsontype.go | 16 ++++++++++++++++ internal/server/utils/jsontype_test.go | 16 ++++++++++++++++ internal/server/utils/round.go | 16 ++++++++++++++++ internal/server/utils/time.go | 16 ++++++++++++++++ internal/shard/shard_manager.go | 16 ++++++++++++++++ internal/shard/shard_thread.go | 16 ++++++++++++++++ internal/sql/constants.go | 16 ++++++++++++++++ internal/sql/dsql.go | 16 ++++++++++++++++ internal/sql/dsql_test.go | 16 ++++++++++++++++ internal/sql/executerbechmark_test.go | 16 ++++++++++++++++ internal/sql/executor.go | 16 ++++++++++++++++ internal/sql/executor_test.go | 16 ++++++++++++++++ internal/sql/fingerprint.go | 16 ++++++++++++++++ internal/sql/fingerprint_test.go | 16 ++++++++++++++++ internal/store/aof.go | 16 ++++++++++++++++ internal/store/aof_test.go | 16 ++++++++++++++++ internal/store/batchevictionlru.go | 16 ++++++++++++++++ internal/store/batchevictionlru_test.go | 16 ++++++++++++++++ internal/store/constants.go | 16 ++++++++++++++++ internal/store/eviction.go | 16 ++++++++++++++++ internal/store/expire.go | 16 ++++++++++++++++ internal/store/expire_test.go | 16 ++++++++++++++++ internal/store/store.go | 16 ++++++++++++++++ internal/store/store_options.go | 16 ++++++++++++++++ internal/wal/wal.go | 16 ++++++++++++++++ internal/wal/wal.pb.go | 16 ++++++++++++++++ internal/wal/wal.proto | 16 ++++++++++++++++ internal/wal/wal_aof.go | 16 ++++++++++++++++ internal/wal/wal_null.go | 16 ++++++++++++++++ internal/wal/wal_sqlite.go | 16 ++++++++++++++++ internal/wal/wal_test.go | 16 ++++++++++++++++ internal/watchmanager/watch_manager.go | 16 ++++++++++++++++ main.go | 16 ++++++++++++++++ mocks/slog_noop.go | 16 ++++++++++++++++ testutils/json.go | 16 ++++++++++++++++ testutils/parsecommand.go | 16 ++++++++++++++++ testutils/slices.go | 16 ++++++++++++++++ 322 files changed, 5152 insertions(+) diff --git a/config/config.go b/config/config.go index 98d1fc64f..a99b3b697 100644 --- a/config/config.go +++ b/config/config.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package config import ( diff --git a/config/parser.go b/config/parser.go index 937ff9f5b..d8107ae75 100644 --- a/config/parser.go +++ b/config/parser.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package config import ( diff --git a/config/validator.go b/config/validator.go index 66669ff43..1372b6bca 100644 --- a/config/validator.go +++ b/config/validator.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package config import ( diff --git a/examples/leaderboard-go/main.go b/examples/leaderboard-go/main.go index eeb2b1101..92899b97c 100644 --- a/examples/leaderboard-go/main.go +++ b/examples/leaderboard-go/main.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package main import ( diff --git a/examples/url-shortener/main.go b/examples/url-shortener/main.go index 583eb8a02..a547b8b37 100644 --- a/examples/url-shortener/main.go +++ b/examples/url-shortener/main.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package main import ( diff --git a/integration_tests/commands/http/append_test.go b/integration_tests/commands/http/append_test.go index 5c4150ae2..3fc9881e8 100644 --- a/integration_tests/commands/http/append_test.go +++ b/integration_tests/commands/http/append_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/bit_test.go b/integration_tests/commands/http/bit_test.go index 1d6418cde..5934415c9 100644 --- a/integration_tests/commands/http/bit_test.go +++ b/integration_tests/commands/http/bit_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http // The following commands are a part of this test class: diff --git a/integration_tests/commands/http/bloom_test.go b/integration_tests/commands/http/bloom_test.go index 8d28958b9..f4d323c9a 100644 --- a/integration_tests/commands/http/bloom_test.go +++ b/integration_tests/commands/http/bloom_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/check_type_test.go b/integration_tests/commands/http/check_type_test.go index 81127f284..02e2abd83 100644 --- a/integration_tests/commands/http/check_type_test.go +++ b/integration_tests/commands/http/check_type_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/command_count_test.go b/integration_tests/commands/http/command_count_test.go index dd9e55338..7c9e12e2e 100644 --- a/integration_tests/commands/http/command_count_test.go +++ b/integration_tests/commands/http/command_count_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/command_default_test.go b/integration_tests/commands/http/command_default_test.go index c4a67a8c7..2b5806364 100644 --- a/integration_tests/commands/http/command_default_test.go +++ b/integration_tests/commands/http/command_default_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/command_docs_test.go b/integration_tests/commands/http/command_docs_test.go index 801e18897..b5cddd097 100644 --- a/integration_tests/commands/http/command_docs_test.go +++ b/integration_tests/commands/http/command_docs_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/command_getkeys_test.go b/integration_tests/commands/http/command_getkeys_test.go index 3ebb1074a..9d5f52846 100644 --- a/integration_tests/commands/http/command_getkeys_test.go +++ b/integration_tests/commands/http/command_getkeys_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/command_help_test.go b/integration_tests/commands/http/command_help_test.go index d39af3044..b047fb365 100644 --- a/integration_tests/commands/http/command_help_test.go +++ b/integration_tests/commands/http/command_help_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/command_info_test.go b/integration_tests/commands/http/command_info_test.go index e7639a7c9..4b9da0479 100644 --- a/integration_tests/commands/http/command_info_test.go +++ b/integration_tests/commands/http/command_info_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/command_list_test.go b/integration_tests/commands/http/command_list_test.go index 87ed4508f..40c344a7f 100644 --- a/integration_tests/commands/http/command_list_test.go +++ b/integration_tests/commands/http/command_list_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/command_rename_test.go b/integration_tests/commands/http/command_rename_test.go index 0c9845060..0411c5e4b 100644 --- a/integration_tests/commands/http/command_rename_test.go +++ b/integration_tests/commands/http/command_rename_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + //go:build ignore // +build ignore diff --git a/integration_tests/commands/http/copy_test.go b/integration_tests/commands/http/copy_test.go index fc46da0ce..91fec81d1 100644 --- a/integration_tests/commands/http/copy_test.go +++ b/integration_tests/commands/http/copy_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + //go:build ignore // +build ignore diff --git a/integration_tests/commands/http/countminsketch_test.go b/integration_tests/commands/http/countminsketch_test.go index bc051a147..4b9a739cd 100644 --- a/integration_tests/commands/http/countminsketch_test.go +++ b/integration_tests/commands/http/countminsketch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/dbsize_test.go b/integration_tests/commands/http/dbsize_test.go index 430abab5e..dc436ce40 100644 --- a/integration_tests/commands/http/dbsize_test.go +++ b/integration_tests/commands/http/dbsize_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + //go:build ignore // +build ignore diff --git a/integration_tests/commands/http/decr_test.go b/integration_tests/commands/http/decr_test.go index a41fc53d3..d5d933ae6 100644 --- a/integration_tests/commands/http/decr_test.go +++ b/integration_tests/commands/http/decr_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/del_test.go b/integration_tests/commands/http/del_test.go index e6df09465..a189942ba 100644 --- a/integration_tests/commands/http/del_test.go +++ b/integration_tests/commands/http/del_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/deque_test.go b/integration_tests/commands/http/deque_test.go index cb1582ce7..562a249e6 100644 --- a/integration_tests/commands/http/deque_test.go +++ b/integration_tests/commands/http/deque_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/echo_test.go b/integration_tests/commands/http/echo_test.go index d2f8db08c..260499aa7 100644 --- a/integration_tests/commands/http/echo_test.go +++ b/integration_tests/commands/http/echo_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/exists_test.go b/integration_tests/commands/http/exists_test.go index a7da3bd66..160378793 100644 --- a/integration_tests/commands/http/exists_test.go +++ b/integration_tests/commands/http/exists_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/expire_test.go b/integration_tests/commands/http/expire_test.go index f785e89f8..029e7aa2f 100644 --- a/integration_tests/commands/http/expire_test.go +++ b/integration_tests/commands/http/expire_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/expireat_test.go b/integration_tests/commands/http/expireat_test.go index 371c233d4..a9ef6dc72 100644 --- a/integration_tests/commands/http/expireat_test.go +++ b/integration_tests/commands/http/expireat_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/expiretime_test.go b/integration_tests/commands/http/expiretime_test.go index f3d4f0491..49421decd 100644 --- a/integration_tests/commands/http/expiretime_test.go +++ b/integration_tests/commands/http/expiretime_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/geo_test.go b/integration_tests/commands/http/geo_test.go index 2943c3fa2..4d0a42d73 100644 --- a/integration_tests/commands/http/geo_test.go +++ b/integration_tests/commands/http/geo_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/get_test.go b/integration_tests/commands/http/get_test.go index 392ea42c6..d66e0429b 100644 --- a/integration_tests/commands/http/get_test.go +++ b/integration_tests/commands/http/get_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/getdel_test.go b/integration_tests/commands/http/getdel_test.go index 9233a0b90..fca983230 100644 --- a/integration_tests/commands/http/getdel_test.go +++ b/integration_tests/commands/http/getdel_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/getex_test.go b/integration_tests/commands/http/getex_test.go index 12fb9d03b..e232e3286 100644 --- a/integration_tests/commands/http/getex_test.go +++ b/integration_tests/commands/http/getex_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/getrange_test.go b/integration_tests/commands/http/getrange_test.go index e4c7c941e..dc47b8145 100644 --- a/integration_tests/commands/http/getrange_test.go +++ b/integration_tests/commands/http/getrange_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/getset_test.go b/integration_tests/commands/http/getset_test.go index 0072eee92..60fc7a58c 100644 --- a/integration_tests/commands/http/getset_test.go +++ b/integration_tests/commands/http/getset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hdel_test.go b/integration_tests/commands/http/hdel_test.go index a955fc274..81e76a5aa 100644 --- a/integration_tests/commands/http/hdel_test.go +++ b/integration_tests/commands/http/hdel_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hexists_test.go b/integration_tests/commands/http/hexists_test.go index 2013810a1..116bc8052 100644 --- a/integration_tests/commands/http/hexists_test.go +++ b/integration_tests/commands/http/hexists_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hget_test.go b/integration_tests/commands/http/hget_test.go index 364fdc0d2..b607d1ac6 100644 --- a/integration_tests/commands/http/hget_test.go +++ b/integration_tests/commands/http/hget_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hincrby_test.go b/integration_tests/commands/http/hincrby_test.go index c01590762..9eca44c51 100644 --- a/integration_tests/commands/http/hincrby_test.go +++ b/integration_tests/commands/http/hincrby_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hincrbyfloat_test.go b/integration_tests/commands/http/hincrbyfloat_test.go index 94b42e8e9..a715cca55 100644 --- a/integration_tests/commands/http/hincrbyfloat_test.go +++ b/integration_tests/commands/http/hincrbyfloat_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hkeys_test.go b/integration_tests/commands/http/hkeys_test.go index b93373669..4c8acc475 100644 --- a/integration_tests/commands/http/hkeys_test.go +++ b/integration_tests/commands/http/hkeys_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hlen_test.go b/integration_tests/commands/http/hlen_test.go index 91daef6f4..42bb113be 100644 --- a/integration_tests/commands/http/hlen_test.go +++ b/integration_tests/commands/http/hlen_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hrandfield_test.go b/integration_tests/commands/http/hrandfield_test.go index 2067e9fe8..74d6945fd 100644 --- a/integration_tests/commands/http/hrandfield_test.go +++ b/integration_tests/commands/http/hrandfield_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hscan_test.go b/integration_tests/commands/http/hscan_test.go index d3c048210..690a8db2c 100644 --- a/integration_tests/commands/http/hscan_test.go +++ b/integration_tests/commands/http/hscan_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hset_test.go b/integration_tests/commands/http/hset_test.go index e17bf6574..baeb4beb3 100644 --- a/integration_tests/commands/http/hset_test.go +++ b/integration_tests/commands/http/hset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hsetnx_test.go b/integration_tests/commands/http/hsetnx_test.go index 133ab883c..84760e619 100644 --- a/integration_tests/commands/http/hsetnx_test.go +++ b/integration_tests/commands/http/hsetnx_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hstrlen_test.go b/integration_tests/commands/http/hstrlen_test.go index 7e4685463..602d23fe1 100644 --- a/integration_tests/commands/http/hstrlen_test.go +++ b/integration_tests/commands/http/hstrlen_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hvals_test.go b/integration_tests/commands/http/hvals_test.go index 7b0c3b2e1..04eca2d32 100644 --- a/integration_tests/commands/http/hvals_test.go +++ b/integration_tests/commands/http/hvals_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/hyperloglog_test.go b/integration_tests/commands/http/hyperloglog_test.go index 70ac1e807..562ae3c8a 100644 --- a/integration_tests/commands/http/hyperloglog_test.go +++ b/integration_tests/commands/http/hyperloglog_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/incr_by_float_test.go b/integration_tests/commands/http/incr_by_float_test.go index d38c2fe0a..110c18113 100644 --- a/integration_tests/commands/http/incr_by_float_test.go +++ b/integration_tests/commands/http/incr_by_float_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/incr_test.go b/integration_tests/commands/http/incr_test.go index fa2aeaf3a..407f22368 100644 --- a/integration_tests/commands/http/incr_test.go +++ b/integration_tests/commands/http/incr_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/json_arrpop_test.go b/integration_tests/commands/http/json_arrpop_test.go index b564a6a8f..8493b9d4f 100644 --- a/integration_tests/commands/http/json_arrpop_test.go +++ b/integration_tests/commands/http/json_arrpop_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/json_test.go b/integration_tests/commands/http/json_test.go index ebcee8c07..b0a2700bd 100644 --- a/integration_tests/commands/http/json_test.go +++ b/integration_tests/commands/http/json_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/jsondebug_test.go b/integration_tests/commands/http/jsondebug_test.go index 37ab3a061..0bc197746 100644 --- a/integration_tests/commands/http/jsondebug_test.go +++ b/integration_tests/commands/http/jsondebug_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/jsonresp_test.go b/integration_tests/commands/http/jsonresp_test.go index b408dbb1a..e0f2be2b6 100644 --- a/integration_tests/commands/http/jsonresp_test.go +++ b/integration_tests/commands/http/jsonresp_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/keys_test.go b/integration_tests/commands/http/keys_test.go index 6219a3945..a23136259 100644 --- a/integration_tests/commands/http/keys_test.go +++ b/integration_tests/commands/http/keys_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + //go:build ignore // +build ignore diff --git a/integration_tests/commands/http/main_test.go b/integration_tests/commands/http/main_test.go index 0e480a37e..b2c5ac3f9 100644 --- a/integration_tests/commands/http/main_test.go +++ b/integration_tests/commands/http/main_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/mget_test.go b/integration_tests/commands/http/mget_test.go index ae85f68ff..01d68507a 100644 --- a/integration_tests/commands/http/mget_test.go +++ b/integration_tests/commands/http/mget_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + //go:build ignore // +build ignore diff --git a/integration_tests/commands/http/mset_test.go b/integration_tests/commands/http/mset_test.go index 7a0d47f87..4383f6e99 100644 --- a/integration_tests/commands/http/mset_test.go +++ b/integration_tests/commands/http/mset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + //go:build ignore // +build ignore diff --git a/integration_tests/commands/http/object_test.go b/integration_tests/commands/http/object_test.go index b0b105883..db9d5293a 100644 --- a/integration_tests/commands/http/object_test.go +++ b/integration_tests/commands/http/object_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + //go:build ignore // +build ignore diff --git a/integration_tests/commands/http/set_data_cmd_test.go b/integration_tests/commands/http/set_data_cmd_test.go index adbd66bce..561347020 100644 --- a/integration_tests/commands/http/set_data_cmd_test.go +++ b/integration_tests/commands/http/set_data_cmd_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/set_test.go b/integration_tests/commands/http/set_test.go index 84c10f8d8..6c1803196 100644 --- a/integration_tests/commands/http/set_test.go +++ b/integration_tests/commands/http/set_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/setup.go b/integration_tests/commands/http/setup.go index 24ef1aa00..2e257026d 100644 --- a/integration_tests/commands/http/setup.go +++ b/integration_tests/commands/http/setup.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/touch_test.go b/integration_tests/commands/http/touch_test.go index 454a24821..7133069e1 100644 --- a/integration_tests/commands/http/touch_test.go +++ b/integration_tests/commands/http/touch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + //go:build ignore // +build ignore diff --git a/integration_tests/commands/http/ttl_pttl_test.go b/integration_tests/commands/http/ttl_pttl_test.go index 0d3f8ce37..dffb88c9c 100644 --- a/integration_tests/commands/http/ttl_pttl_test.go +++ b/integration_tests/commands/http/ttl_pttl_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/type_test.go b/integration_tests/commands/http/type_test.go index 7342f002f..43a04f02b 100644 --- a/integration_tests/commands/http/type_test.go +++ b/integration_tests/commands/http/type_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/zcard_test.go b/integration_tests/commands/http/zcard_test.go index 29c869d97..b729be37c 100644 --- a/integration_tests/commands/http/zcard_test.go +++ b/integration_tests/commands/http/zcard_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/zpopmax_test.go b/integration_tests/commands/http/zpopmax_test.go index 971f31924..79ac01bd9 100644 --- a/integration_tests/commands/http/zpopmax_test.go +++ b/integration_tests/commands/http/zpopmax_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/zrank_test.go b/integration_tests/commands/http/zrank_test.go index 82bdc6558..7f8c00665 100644 --- a/integration_tests/commands/http/zrank_test.go +++ b/integration_tests/commands/http/zrank_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/zrem_test.go b/integration_tests/commands/http/zrem_test.go index 733c5c793..7105efe41 100644 --- a/integration_tests/commands/http/zrem_test.go +++ b/integration_tests/commands/http/zrem_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/http/zset_test.go b/integration_tests/commands/http/zset_test.go index 1b54678e9..8ce42cb6b 100644 --- a/integration_tests/commands/http/zset_test.go +++ b/integration_tests/commands/http/zset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package http import ( diff --git a/integration_tests/commands/resp/abort/server_abort_test.go b/integration_tests/commands/resp/abort/server_abort_test.go index b7515839e..0bafdaa2e 100644 --- a/integration_tests/commands/resp/abort/server_abort_test.go +++ b/integration_tests/commands/resp/abort/server_abort_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package abort import ( diff --git a/integration_tests/commands/resp/append_test.go b/integration_tests/commands/resp/append_test.go index 85829fa66..4b6aa1a81 100644 --- a/integration_tests/commands/resp/append_test.go +++ b/integration_tests/commands/resp/append_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/bit_test.go b/integration_tests/commands/resp/bit_test.go index 7d7d48212..db14a4a9d 100644 --- a/integration_tests/commands/resp/bit_test.go +++ b/integration_tests/commands/resp/bit_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp // The following commands are a part of this test class: diff --git a/integration_tests/commands/resp/bloom_test.go b/integration_tests/commands/resp/bloom_test.go index 5af5b3044..14e6f2f4e 100644 --- a/integration_tests/commands/resp/bloom_test.go +++ b/integration_tests/commands/resp/bloom_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/check_type_test.go b/integration_tests/commands/resp/check_type_test.go index 80530c77b..b3d280f0d 100644 --- a/integration_tests/commands/resp/check_type_test.go +++ b/integration_tests/commands/resp/check_type_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/command_count_test.go b/integration_tests/commands/resp/command_count_test.go index 7112e9dbb..33b4dcaf0 100644 --- a/integration_tests/commands/resp/command_count_test.go +++ b/integration_tests/commands/resp/command_count_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/command_default_test.go b/integration_tests/commands/resp/command_default_test.go index 8ca752e5b..543100005 100644 --- a/integration_tests/commands/resp/command_default_test.go +++ b/integration_tests/commands/resp/command_default_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/command_docs_test.go b/integration_tests/commands/resp/command_docs_test.go index 25fe40f78..a344c69e0 100644 --- a/integration_tests/commands/resp/command_docs_test.go +++ b/integration_tests/commands/resp/command_docs_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/command_getkeys_test.go b/integration_tests/commands/resp/command_getkeys_test.go index 166079b4b..228fe409c 100644 --- a/integration_tests/commands/resp/command_getkeys_test.go +++ b/integration_tests/commands/resp/command_getkeys_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/command_info_test.go b/integration_tests/commands/resp/command_info_test.go index e9d71ff5a..76c849d55 100644 --- a/integration_tests/commands/resp/command_info_test.go +++ b/integration_tests/commands/resp/command_info_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/command_list_test.go b/integration_tests/commands/resp/command_list_test.go index 57d5513e7..a6dbeb590 100644 --- a/integration_tests/commands/resp/command_list_test.go +++ b/integration_tests/commands/resp/command_list_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/command_rename_test.go b/integration_tests/commands/resp/command_rename_test.go index bff051cba..1d3976379 100644 --- a/integration_tests/commands/resp/command_rename_test.go +++ b/integration_tests/commands/resp/command_rename_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/copy_test.go b/integration_tests/commands/resp/copy_test.go index 95f8817ae..f9db9951c 100644 --- a/integration_tests/commands/resp/copy_test.go +++ b/integration_tests/commands/resp/copy_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/countminsketch_test.go b/integration_tests/commands/resp/countminsketch_test.go index e1c66575c..5ee7feb70 100644 --- a/integration_tests/commands/resp/countminsketch_test.go +++ b/integration_tests/commands/resp/countminsketch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/dbsize_test.go b/integration_tests/commands/resp/dbsize_test.go index aee23acf0..1a3db23bb 100644 --- a/integration_tests/commands/resp/dbsize_test.go +++ b/integration_tests/commands/resp/dbsize_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/decr_test.go b/integration_tests/commands/resp/decr_test.go index dfe06b2e3..625ad5fc3 100644 --- a/integration_tests/commands/resp/decr_test.go +++ b/integration_tests/commands/resp/decr_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/del_test.go b/integration_tests/commands/resp/del_test.go index bf02a80bf..780ba9c64 100644 --- a/integration_tests/commands/resp/del_test.go +++ b/integration_tests/commands/resp/del_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/deque_test.go b/integration_tests/commands/resp/deque_test.go index db69db3ce..d80263633 100644 --- a/integration_tests/commands/resp/deque_test.go +++ b/integration_tests/commands/resp/deque_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/dump_test.go b/integration_tests/commands/resp/dump_test.go index 27d50badb..35326855f 100644 --- a/integration_tests/commands/resp/dump_test.go +++ b/integration_tests/commands/resp/dump_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/echo_test.go b/integration_tests/commands/resp/echo_test.go index e21df6798..50a2eac93 100644 --- a/integration_tests/commands/resp/echo_test.go +++ b/integration_tests/commands/resp/echo_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/exists_test.go b/integration_tests/commands/resp/exists_test.go index 1b8ec6d26..6f5828f9c 100644 --- a/integration_tests/commands/resp/exists_test.go +++ b/integration_tests/commands/resp/exists_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/expire_test.go b/integration_tests/commands/resp/expire_test.go index 12b2e71c9..f85ef0ea6 100644 --- a/integration_tests/commands/resp/expire_test.go +++ b/integration_tests/commands/resp/expire_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/flushdb_test.go b/integration_tests/commands/resp/flushdb_test.go index 59cc2d506..df652758e 100644 --- a/integration_tests/commands/resp/flushdb_test.go +++ b/integration_tests/commands/resp/flushdb_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/geo_test.go b/integration_tests/commands/resp/geo_test.go index b6eefc927..ba4a1d400 100644 --- a/integration_tests/commands/resp/geo_test.go +++ b/integration_tests/commands/resp/geo_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/get_test.go b/integration_tests/commands/resp/get_test.go index a7dc5f118..4358a139d 100644 --- a/integration_tests/commands/resp/get_test.go +++ b/integration_tests/commands/resp/get_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/getdel_test.go b/integration_tests/commands/resp/getdel_test.go index b92cf7582..3b5459121 100644 --- a/integration_tests/commands/resp/getdel_test.go +++ b/integration_tests/commands/resp/getdel_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/getex_test.go b/integration_tests/commands/resp/getex_test.go index 94fa5434f..dabb5c1c0 100644 --- a/integration_tests/commands/resp/getex_test.go +++ b/integration_tests/commands/resp/getex_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/getrange_test.go b/integration_tests/commands/resp/getrange_test.go index 343654f6d..00a3e5e05 100644 --- a/integration_tests/commands/resp/getrange_test.go +++ b/integration_tests/commands/resp/getrange_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/getset_test.go b/integration_tests/commands/resp/getset_test.go index 8846bae9e..1dadf2595 100644 --- a/integration_tests/commands/resp/getset_test.go +++ b/integration_tests/commands/resp/getset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/getunwatch_test.go b/integration_tests/commands/resp/getunwatch_test.go index 2adf4f234..92e63f441 100644 --- a/integration_tests/commands/resp/getunwatch_test.go +++ b/integration_tests/commands/resp/getunwatch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/getwatch_test.go b/integration_tests/commands/resp/getwatch_test.go index 177007e12..8bcf32a40 100644 --- a/integration_tests/commands/resp/getwatch_test.go +++ b/integration_tests/commands/resp/getwatch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hdel_test.go b/integration_tests/commands/resp/hdel_test.go index f931f781a..a0f57c166 100644 --- a/integration_tests/commands/resp/hdel_test.go +++ b/integration_tests/commands/resp/hdel_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hello_test.go b/integration_tests/commands/resp/hello_test.go index 015a2553e..e3f6b2a20 100644 --- a/integration_tests/commands/resp/hello_test.go +++ b/integration_tests/commands/resp/hello_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hexists_test.go b/integration_tests/commands/resp/hexists_test.go index 65ab8914e..6b294187a 100644 --- a/integration_tests/commands/resp/hexists_test.go +++ b/integration_tests/commands/resp/hexists_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hget_test.go b/integration_tests/commands/resp/hget_test.go index 79489550b..e6aac7fc8 100644 --- a/integration_tests/commands/resp/hget_test.go +++ b/integration_tests/commands/resp/hget_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hgetall_test.go b/integration_tests/commands/resp/hgetall_test.go index c179d9b7e..cc7a7cb2e 100644 --- a/integration_tests/commands/resp/hgetall_test.go +++ b/integration_tests/commands/resp/hgetall_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hincrby_test.go b/integration_tests/commands/resp/hincrby_test.go index 01f694a3b..42bf19ce3 100644 --- a/integration_tests/commands/resp/hincrby_test.go +++ b/integration_tests/commands/resp/hincrby_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hincrbyfloat_test.go b/integration_tests/commands/resp/hincrbyfloat_test.go index df16faeb7..8b908315d 100644 --- a/integration_tests/commands/resp/hincrbyfloat_test.go +++ b/integration_tests/commands/resp/hincrbyfloat_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hkeys_test.go b/integration_tests/commands/resp/hkeys_test.go index 92597730b..4d6d408e0 100644 --- a/integration_tests/commands/resp/hkeys_test.go +++ b/integration_tests/commands/resp/hkeys_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hlen_test.go b/integration_tests/commands/resp/hlen_test.go index eae9b1be8..416c1c90b 100644 --- a/integration_tests/commands/resp/hlen_test.go +++ b/integration_tests/commands/resp/hlen_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hmget_test.go b/integration_tests/commands/resp/hmget_test.go index ad946e9cf..22e5c9898 100644 --- a/integration_tests/commands/resp/hmget_test.go +++ b/integration_tests/commands/resp/hmget_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hmset_test.go b/integration_tests/commands/resp/hmset_test.go index 44e68d0a6..371ab8025 100644 --- a/integration_tests/commands/resp/hmset_test.go +++ b/integration_tests/commands/resp/hmset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hrandfield_test.go b/integration_tests/commands/resp/hrandfield_test.go index 45f879a7d..70e5a75d4 100644 --- a/integration_tests/commands/resp/hrandfield_test.go +++ b/integration_tests/commands/resp/hrandfield_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hscan_test.go b/integration_tests/commands/resp/hscan_test.go index d019cb852..ec1f0ba2e 100644 --- a/integration_tests/commands/resp/hscan_test.go +++ b/integration_tests/commands/resp/hscan_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hset_test.go b/integration_tests/commands/resp/hset_test.go index 272df8889..8d85b5e8a 100644 --- a/integration_tests/commands/resp/hset_test.go +++ b/integration_tests/commands/resp/hset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hsetnx_test.go b/integration_tests/commands/resp/hsetnx_test.go index 8e59e3160..1970ba63e 100644 --- a/integration_tests/commands/resp/hsetnx_test.go +++ b/integration_tests/commands/resp/hsetnx_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hstrlen_test.go b/integration_tests/commands/resp/hstrlen_test.go index 28c51bf13..793646ad4 100644 --- a/integration_tests/commands/resp/hstrlen_test.go +++ b/integration_tests/commands/resp/hstrlen_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hvals_test.go b/integration_tests/commands/resp/hvals_test.go index ca0a10dfe..ff0690187 100644 --- a/integration_tests/commands/resp/hvals_test.go +++ b/integration_tests/commands/resp/hvals_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/hyperloglog_test.go b/integration_tests/commands/resp/hyperloglog_test.go index d6e09a3c7..d927220d7 100644 --- a/integration_tests/commands/resp/hyperloglog_test.go +++ b/integration_tests/commands/resp/hyperloglog_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp // All commands related to Hyperloglog are part of this test class diff --git a/integration_tests/commands/resp/incr_by_float_test.go b/integration_tests/commands/resp/incr_by_float_test.go index e47bdf717..b7a2f6935 100644 --- a/integration_tests/commands/resp/incr_by_float_test.go +++ b/integration_tests/commands/resp/incr_by_float_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/incr_test.go b/integration_tests/commands/resp/incr_test.go index 24077f925..9fa2a1404 100644 --- a/integration_tests/commands/resp/incr_test.go +++ b/integration_tests/commands/resp/incr_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/json_test.go b/integration_tests/commands/resp/json_test.go index c2c498a32..254ced30d 100644 --- a/integration_tests/commands/resp/json_test.go +++ b/integration_tests/commands/resp/json_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/jsondebug_test.go b/integration_tests/commands/resp/jsondebug_test.go index 8ad10a9ae..e76230d90 100644 --- a/integration_tests/commands/resp/jsondebug_test.go +++ b/integration_tests/commands/resp/jsondebug_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/jsonresp_test.go b/integration_tests/commands/resp/jsonresp_test.go index 9078c91af..947d2bf88 100644 --- a/integration_tests/commands/resp/jsonresp_test.go +++ b/integration_tests/commands/resp/jsonresp_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/keys_test.go b/integration_tests/commands/resp/keys_test.go index cf548152c..5ce99d427 100644 --- a/integration_tests/commands/resp/keys_test.go +++ b/integration_tests/commands/resp/keys_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/main_test.go b/integration_tests/commands/resp/main_test.go index 757c98083..7e0ab3a5d 100644 --- a/integration_tests/commands/resp/main_test.go +++ b/integration_tests/commands/resp/main_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/mget_test.go b/integration_tests/commands/resp/mget_test.go index 2df676e08..79850e4aa 100644 --- a/integration_tests/commands/resp/mget_test.go +++ b/integration_tests/commands/resp/mget_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/mset_test.go b/integration_tests/commands/resp/mset_test.go index 0e82a179a..391b5e0c9 100644 --- a/integration_tests/commands/resp/mset_test.go +++ b/integration_tests/commands/resp/mset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/object_test.go b/integration_tests/commands/resp/object_test.go index cd6c9cd74..9fb23cf79 100644 --- a/integration_tests/commands/resp/object_test.go +++ b/integration_tests/commands/resp/object_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/pfcountwatch_test.go b/integration_tests/commands/resp/pfcountwatch_test.go index 84ec4f316..5d5f1776e 100644 --- a/integration_tests/commands/resp/pfcountwatch_test.go +++ b/integration_tests/commands/resp/pfcountwatch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/set_data_cmd_test.go b/integration_tests/commands/resp/set_data_cmd_test.go index 5efb0bf75..7376e584f 100644 --- a/integration_tests/commands/resp/set_data_cmd_test.go +++ b/integration_tests/commands/resp/set_data_cmd_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/set_test.go b/integration_tests/commands/resp/set_test.go index dc07883f9..dee56f95c 100644 --- a/integration_tests/commands/resp/set_test.go +++ b/integration_tests/commands/resp/set_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/setup.go b/integration_tests/commands/resp/setup.go index b98cdd31c..0e55e890b 100644 --- a/integration_tests/commands/resp/setup.go +++ b/integration_tests/commands/resp/setup.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/touch_test.go b/integration_tests/commands/resp/touch_test.go index 17ef6e4f9..cf291e2ff 100644 --- a/integration_tests/commands/resp/touch_test.go +++ b/integration_tests/commands/resp/touch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/ttl_pttl_test.go b/integration_tests/commands/resp/ttl_pttl_test.go index 4853196d4..42546992b 100644 --- a/integration_tests/commands/resp/ttl_pttl_test.go +++ b/integration_tests/commands/resp/ttl_pttl_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/type_test.go b/integration_tests/commands/resp/type_test.go index a67f63c53..482fc7b71 100644 --- a/integration_tests/commands/resp/type_test.go +++ b/integration_tests/commands/resp/type_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/zcard_test.go b/integration_tests/commands/resp/zcard_test.go index b799ae170..b5e4a445d 100644 --- a/integration_tests/commands/resp/zcard_test.go +++ b/integration_tests/commands/resp/zcard_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/zpopmax_test.go b/integration_tests/commands/resp/zpopmax_test.go index f89389259..832ce5bee 100644 --- a/integration_tests/commands/resp/zpopmax_test.go +++ b/integration_tests/commands/resp/zpopmax_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/zrangewatch_test.go b/integration_tests/commands/resp/zrangewatch_test.go index 2f518b056..3fa93d9c2 100644 --- a/integration_tests/commands/resp/zrangewatch_test.go +++ b/integration_tests/commands/resp/zrangewatch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/zrank_test.go b/integration_tests/commands/resp/zrank_test.go index 3f0dc552e..f8affe50f 100644 --- a/integration_tests/commands/resp/zrank_test.go +++ b/integration_tests/commands/resp/zrank_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/zrem_test.go b/integration_tests/commands/resp/zrem_test.go index 7ff8956bb..13fc14f83 100644 --- a/integration_tests/commands/resp/zrem_test.go +++ b/integration_tests/commands/resp/zrem_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/resp/zset_test.go b/integration_tests/commands/resp/zset_test.go index 60e3b7196..d5f64909a 100644 --- a/integration_tests/commands/resp/zset_test.go +++ b/integration_tests/commands/resp/zset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/integration_tests/commands/websocket/append_test.go b/integration_tests/commands/websocket/append_test.go index a04e4d1d3..55eea5b93 100644 --- a/integration_tests/commands/websocket/append_test.go +++ b/integration_tests/commands/websocket/append_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/bit_test.go b/integration_tests/commands/websocket/bit_test.go index f2a97e5be..1e0ebdf19 100644 --- a/integration_tests/commands/websocket/bit_test.go +++ b/integration_tests/commands/websocket/bit_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/bloom_test.go b/integration_tests/commands/websocket/bloom_test.go index d8c9222ca..af2c17a10 100644 --- a/integration_tests/commands/websocket/bloom_test.go +++ b/integration_tests/commands/websocket/bloom_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/command_docs_test.go b/integration_tests/commands/websocket/command_docs_test.go index 6daa42571..f6f999402 100644 --- a/integration_tests/commands/websocket/command_docs_test.go +++ b/integration_tests/commands/websocket/command_docs_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/countminsketch_test.go b/integration_tests/commands/websocket/countminsketch_test.go index f6e168bc4..4f6b52561 100644 --- a/integration_tests/commands/websocket/countminsketch_test.go +++ b/integration_tests/commands/websocket/countminsketch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/decr_test.go b/integration_tests/commands/websocket/decr_test.go index 6727f05b1..62d59a024 100644 --- a/integration_tests/commands/websocket/decr_test.go +++ b/integration_tests/commands/websocket/decr_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/del_test.go b/integration_tests/commands/websocket/del_test.go index db00c056e..e2b8e821d 100644 --- a/integration_tests/commands/websocket/del_test.go +++ b/integration_tests/commands/websocket/del_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/deque_test.go b/integration_tests/commands/websocket/deque_test.go index ff986e111..1b98e7452 100644 --- a/integration_tests/commands/websocket/deque_test.go +++ b/integration_tests/commands/websocket/deque_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/exists_test.go b/integration_tests/commands/websocket/exists_test.go index eea311ef2..1a90ff867 100644 --- a/integration_tests/commands/websocket/exists_test.go +++ b/integration_tests/commands/websocket/exists_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/expire_test.go b/integration_tests/commands/websocket/expire_test.go index 9cf9e8713..a46a96dc4 100644 --- a/integration_tests/commands/websocket/expire_test.go +++ b/integration_tests/commands/websocket/expire_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/geo_test.go b/integration_tests/commands/websocket/geo_test.go index e7402f7de..65723f950 100644 --- a/integration_tests/commands/websocket/geo_test.go +++ b/integration_tests/commands/websocket/geo_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/get_test.go b/integration_tests/commands/websocket/get_test.go index b7b9b5688..26e3e38d1 100644 --- a/integration_tests/commands/websocket/get_test.go +++ b/integration_tests/commands/websocket/get_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/getrange_test.go b/integration_tests/commands/websocket/getrange_test.go index 136d0d0cc..a29ef63c9 100644 --- a/integration_tests/commands/websocket/getrange_test.go +++ b/integration_tests/commands/websocket/getrange_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hdel_test.go b/integration_tests/commands/websocket/hdel_test.go index 92ca4e481..fc5c11319 100644 --- a/integration_tests/commands/websocket/hdel_test.go +++ b/integration_tests/commands/websocket/hdel_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/helper.go b/integration_tests/commands/websocket/helper.go index 1face2836..90c3f359a 100644 --- a/integration_tests/commands/websocket/helper.go +++ b/integration_tests/commands/websocket/helper.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hexists_test.go b/integration_tests/commands/websocket/hexists_test.go index 19c28b1bb..8194d0b70 100644 --- a/integration_tests/commands/websocket/hexists_test.go +++ b/integration_tests/commands/websocket/hexists_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hget_test.go b/integration_tests/commands/websocket/hget_test.go index 36aeb2feb..16b80884f 100644 --- a/integration_tests/commands/websocket/hget_test.go +++ b/integration_tests/commands/websocket/hget_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hincrby_test.go b/integration_tests/commands/websocket/hincrby_test.go index 669ab8973..db589aade 100644 --- a/integration_tests/commands/websocket/hincrby_test.go +++ b/integration_tests/commands/websocket/hincrby_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hincrbyfloat_test.go b/integration_tests/commands/websocket/hincrbyfloat_test.go index a7f76544e..819741df2 100644 --- a/integration_tests/commands/websocket/hincrbyfloat_test.go +++ b/integration_tests/commands/websocket/hincrbyfloat_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hkeys_test.go b/integration_tests/commands/websocket/hkeys_test.go index 16a86291c..66adc00fc 100644 --- a/integration_tests/commands/websocket/hkeys_test.go +++ b/integration_tests/commands/websocket/hkeys_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hlen_test.go b/integration_tests/commands/websocket/hlen_test.go index 093a89dd6..2410809cc 100644 --- a/integration_tests/commands/websocket/hlen_test.go +++ b/integration_tests/commands/websocket/hlen_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hrandfield_test.go b/integration_tests/commands/websocket/hrandfield_test.go index f073f0a6f..a2d34e184 100644 --- a/integration_tests/commands/websocket/hrandfield_test.go +++ b/integration_tests/commands/websocket/hrandfield_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hscan_test.go b/integration_tests/commands/websocket/hscan_test.go index d9f1f8ca2..62e0c2fc8 100644 --- a/integration_tests/commands/websocket/hscan_test.go +++ b/integration_tests/commands/websocket/hscan_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hset_test.go b/integration_tests/commands/websocket/hset_test.go index bc2764de2..dc1f1b551 100644 --- a/integration_tests/commands/websocket/hset_test.go +++ b/integration_tests/commands/websocket/hset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hstrlen_test.go b/integration_tests/commands/websocket/hstrlen_test.go index 3215a0b9e..e84a79f9e 100644 --- a/integration_tests/commands/websocket/hstrlen_test.go +++ b/integration_tests/commands/websocket/hstrlen_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hvals_test.go b/integration_tests/commands/websocket/hvals_test.go index e939a6495..e60401db1 100644 --- a/integration_tests/commands/websocket/hvals_test.go +++ b/integration_tests/commands/websocket/hvals_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/hyperloglog_test.go b/integration_tests/commands/websocket/hyperloglog_test.go index 2da7dfca3..4b4b1586f 100644 --- a/integration_tests/commands/websocket/hyperloglog_test.go +++ b/integration_tests/commands/websocket/hyperloglog_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/incr_by_float_test.go b/integration_tests/commands/websocket/incr_by_float_test.go index 52ba2d3e5..b99532183 100644 --- a/integration_tests/commands/websocket/incr_by_float_test.go +++ b/integration_tests/commands/websocket/incr_by_float_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/incr_test.go b/integration_tests/commands/websocket/incr_test.go index e066e8999..ce21210e0 100644 --- a/integration_tests/commands/websocket/incr_test.go +++ b/integration_tests/commands/websocket/incr_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/json_test.go b/integration_tests/commands/websocket/json_test.go index 71b85a079..de7c84fa9 100644 --- a/integration_tests/commands/websocket/json_test.go +++ b/integration_tests/commands/websocket/json_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/jsondebug_test.go b/integration_tests/commands/websocket/jsondebug_test.go index 77a805f69..3801b9e52 100644 --- a/integration_tests/commands/websocket/jsondebug_test.go +++ b/integration_tests/commands/websocket/jsondebug_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/jsonresp_test.go b/integration_tests/commands/websocket/jsonresp_test.go index aac9aa469..b30fd1588 100644 --- a/integration_tests/commands/websocket/jsonresp_test.go +++ b/integration_tests/commands/websocket/jsonresp_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/main_test.go b/integration_tests/commands/websocket/main_test.go index 1c4ac68bb..4cd01bde6 100644 --- a/integration_tests/commands/websocket/main_test.go +++ b/integration_tests/commands/websocket/main_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/set_test.go b/integration_tests/commands/websocket/set_test.go index 8dac72f15..8d4ade149 100644 --- a/integration_tests/commands/websocket/set_test.go +++ b/integration_tests/commands/websocket/set_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/setup.go b/integration_tests/commands/websocket/setup.go index 281836f30..e9ed697f7 100644 --- a/integration_tests/commands/websocket/setup.go +++ b/integration_tests/commands/websocket/setup.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/ttl_pttl_test.go b/integration_tests/commands/websocket/ttl_pttl_test.go index a87ef2208..b6394db49 100644 --- a/integration_tests/commands/websocket/ttl_pttl_test.go +++ b/integration_tests/commands/websocket/ttl_pttl_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/type_test.go b/integration_tests/commands/websocket/type_test.go index 067d8ebc9..28ab4303e 100644 --- a/integration_tests/commands/websocket/type_test.go +++ b/integration_tests/commands/websocket/type_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/writeretry_test.go b/integration_tests/commands/websocket/writeretry_test.go index 978b836af..b2a2feb72 100644 --- a/integration_tests/commands/websocket/writeretry_test.go +++ b/integration_tests/commands/websocket/writeretry_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/zcard_test.go b/integration_tests/commands/websocket/zcard_test.go index 34561134b..aab00e6c5 100644 --- a/integration_tests/commands/websocket/zcard_test.go +++ b/integration_tests/commands/websocket/zcard_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/zpopmax_test.go b/integration_tests/commands/websocket/zpopmax_test.go index f91557601..753dddc3e 100644 --- a/integration_tests/commands/websocket/zpopmax_test.go +++ b/integration_tests/commands/websocket/zpopmax_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/zrank_test.go b/integration_tests/commands/websocket/zrank_test.go index c48694e35..dc1f496c6 100644 --- a/integration_tests/commands/websocket/zrank_test.go +++ b/integration_tests/commands/websocket/zrank_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/zrem_test.go b/integration_tests/commands/websocket/zrem_test.go index ef8f9e3ae..242b74b83 100644 --- a/integration_tests/commands/websocket/zrem_test.go +++ b/integration_tests/commands/websocket/zrem_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/commands/websocket/zset_test.go b/integration_tests/commands/websocket/zset_test.go index 30c4bfd56..30e6ec3b3 100644 --- a/integration_tests/commands/websocket/zset_test.go +++ b/integration_tests/commands/websocket/zset_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package websocket import ( diff --git a/integration_tests/config/config_test.go b/integration_tests/config/config_test.go index c8063c0b0..d448f733a 100644 --- a/integration_tests/config/config_test.go +++ b/integration_tests/config/config_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package config_test import ( diff --git a/integration_tests/config/parser_test.go b/integration_tests/config/parser_test.go index 31a670288..4e68504d1 100644 --- a/integration_tests/config/parser_test.go +++ b/integration_tests/config/parser_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package config_test import ( diff --git a/integration_tests/server/max_conn_test.go b/integration_tests/server/max_conn_test.go index ded10e2de..3f13c4ac3 100644 --- a/integration_tests/server/max_conn_test.go +++ b/integration_tests/server/max_conn_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package server import ( diff --git a/integration_tests/server/server_abort_test.go b/integration_tests/server/server_abort_test.go index 6b227fa8f..d27f4a6b7 100644 --- a/integration_tests/server/server_abort_test.go +++ b/integration_tests/server/server_abort_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package server import ( diff --git a/integration_tests/server/setup.go b/integration_tests/server/setup.go index b3afe6a18..9ddbe6b77 100644 --- a/integration_tests/server/setup.go +++ b/integration_tests/server/setup.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package server import ( diff --git a/internal/auth/session.go b/internal/auth/session.go index 02f13c506..a9dad704a 100644 --- a/internal/auth/session.go +++ b/internal/auth/session.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package auth import ( diff --git a/internal/auth/session_test.go b/internal/auth/session_test.go index 05f93ae56..01ca56fd0 100644 --- a/internal/auth/session_test.go +++ b/internal/auth/session_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package auth import ( diff --git a/internal/cli/cli.go b/internal/cli/cli.go index 62820dec4..7db447bf3 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package cli import ( diff --git a/internal/clientio/io.go b/internal/clientio/io.go index 1651d6744..ca34404d0 100644 --- a/internal/clientio/io.go +++ b/internal/clientio/io.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package clientio import ( diff --git a/internal/clientio/io_test.go b/internal/clientio/io_test.go index f99e641ba..1f1035d02 100644 --- a/internal/clientio/io_test.go +++ b/internal/clientio/io_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package clientio import ( diff --git a/internal/clientio/iohandler/iohandler.go b/internal/clientio/iohandler/iohandler.go index 3b887a5c8..c922e09b2 100644 --- a/internal/clientio/iohandler/iohandler.go +++ b/internal/clientio/iohandler/iohandler.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iohandler import ( diff --git a/internal/clientio/iohandler/netconn/netconn.go b/internal/clientio/iohandler/netconn/netconn.go index 3079140f6..309bcd86a 100644 --- a/internal/clientio/iohandler/netconn/netconn.go +++ b/internal/clientio/iohandler/netconn/netconn.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package netconn import ( diff --git a/internal/clientio/iohandler/netconn/netconn_resp_test.go b/internal/clientio/iohandler/netconn/netconn_resp_test.go index a391aa922..aa4a67c6c 100644 --- a/internal/clientio/iohandler/netconn/netconn_resp_test.go +++ b/internal/clientio/iohandler/netconn/netconn_resp_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package netconn import ( diff --git a/internal/clientio/iohandler/netconn/netconn_test.go b/internal/clientio/iohandler/netconn/netconn_test.go index a273f2c3d..1c6056a9c 100644 --- a/internal/clientio/iohandler/netconn/netconn_test.go +++ b/internal/clientio/iohandler/netconn/netconn_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package netconn import ( diff --git a/internal/clientio/requestparser/parser.go b/internal/clientio/requestparser/parser.go index 07af168ce..ac0143c79 100644 --- a/internal/clientio/requestparser/parser.go +++ b/internal/clientio/requestparser/parser.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package requestparser import ( diff --git a/internal/clientio/requestparser/resp/respparser.go b/internal/clientio/requestparser/resp/respparser.go index 71ad93eaf..d379a69f9 100644 --- a/internal/clientio/requestparser/resp/respparser.go +++ b/internal/clientio/requestparser/resp/respparser.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package respparser import ( diff --git a/internal/clientio/requestparser/resp/respparser_test.go b/internal/clientio/requestparser/resp/respparser_test.go index bfe553017..e6987bc8e 100644 --- a/internal/clientio/requestparser/resp/respparser_test.go +++ b/internal/clientio/requestparser/resp/respparser_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package respparser import ( diff --git a/internal/clientio/resp.go b/internal/clientio/resp.go index fdfc1dccb..d15119392 100644 --- a/internal/clientio/resp.go +++ b/internal/clientio/resp.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package clientio import ( diff --git a/internal/clientio/resp_test.go b/internal/clientio/resp_test.go index 2ff0c71cc..9e5376e34 100644 --- a/internal/clientio/resp_test.go +++ b/internal/clientio/resp_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package clientio_test import ( diff --git a/internal/cmd/cmds.go b/internal/cmd/cmds.go index d2a955c67..cf886c7ff 100644 --- a/internal/cmd/cmds.go +++ b/internal/cmd/cmds.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package cmd import ( diff --git a/internal/comm/client.go b/internal/comm/client.go index c24736c77..65c05dfd8 100644 --- a/internal/comm/client.go +++ b/internal/comm/client.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package comm import ( diff --git a/internal/common/map.go b/internal/common/map.go index 052dde27c..f9d9a95a4 100644 --- a/internal/common/map.go +++ b/internal/common/map.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package common type ITable[K comparable, V any] interface { diff --git a/internal/common/regmap.go b/internal/common/regmap.go index cc6cf7544..a3afbef70 100644 --- a/internal/common/regmap.go +++ b/internal/common/regmap.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package common type RegMap[K comparable, V any] struct { diff --git a/internal/common/swisstable.go b/internal/common/swisstable.go index d0353e6fb..041e6f41f 100644 --- a/internal/common/swisstable.go +++ b/internal/common/swisstable.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package common import "github.com/cockroachdb/swiss" diff --git a/internal/dencoding/dencoding_benchmark_test.go b/internal/dencoding/dencoding_benchmark_test.go index 66787c403..df178e8ae 100644 --- a/internal/dencoding/dencoding_benchmark_test.go +++ b/internal/dencoding/dencoding_benchmark_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package dencoding_test import ( diff --git a/internal/dencoding/int.go b/internal/dencoding/int.go index 4fd1ccc93..abb4078f0 100644 --- a/internal/dencoding/int.go +++ b/internal/dencoding/int.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package dencoding import "sync" diff --git a/internal/dencoding/int_test.go b/internal/dencoding/int_test.go index 9d2663044..651b3c0d4 100644 --- a/internal/dencoding/int_test.go +++ b/internal/dencoding/int_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package dencoding_test import ( diff --git a/internal/errors/errors.go b/internal/errors/errors.go index 306b94d3c..3d5b28e0a 100644 --- a/internal/errors/errors.go +++ b/internal/errors/errors.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package errors import ( diff --git a/internal/errors/migrated_errors.go b/internal/errors/migrated_errors.go index ea81b0c4e..d456e1456 100644 --- a/internal/errors/migrated_errors.go +++ b/internal/errors/migrated_errors.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package errors import ( diff --git a/internal/eval/bitpos.go b/internal/eval/bitpos.go index 701a5ce74..b3f3c6510 100644 --- a/internal/eval/bitpos.go +++ b/internal/eval/bitpos.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/bloom_test.go b/internal/eval/bloom_test.go index d88d97f2f..a1c5887bc 100644 --- a/internal/eval/bloom_test.go +++ b/internal/eval/bloom_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/bloom_utils.go b/internal/eval/bloom_utils.go index ae297b70c..b53499fed 100644 --- a/internal/eval/bloom_utils.go +++ b/internal/eval/bloom_utils.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval // setBit sets the bit at index `b` to "1" in `buf`. diff --git a/internal/eval/bytearray.go b/internal/eval/bytearray.go index 4bf4f1f0a..b8923e864 100644 --- a/internal/eval/bytearray.go +++ b/internal/eval/bytearray.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/bytearray_test.go b/internal/eval/bytearray_test.go index efaa10f06..b70946c8f 100644 --- a/internal/eval/bytearray_test.go +++ b/internal/eval/bytearray_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/bytelist.go b/internal/eval/bytelist.go index a132a0cce..5c88933d0 100644 --- a/internal/eval/bytelist.go +++ b/internal/eval/bytelist.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/bytelist_test.go b/internal/eval/bytelist_test.go index 2d22d2ebd..e8f5c0408 100644 --- a/internal/eval/bytelist_test.go +++ b/internal/eval/bytelist_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/commands.go b/internal/eval/commands.go index 358279ade..25bb0b1de 100644 --- a/internal/eval/commands.go +++ b/internal/eval/commands.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/constants.go b/internal/eval/constants.go index a7d924b6a..5c9b1ab3c 100644 --- a/internal/eval/constants.go +++ b/internal/eval/constants.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval const ( diff --git a/internal/eval/countminsketch.go b/internal/eval/countminsketch.go index 80a564631..9d8128b05 100644 --- a/internal/eval/countminsketch.go +++ b/internal/eval/countminsketch.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/countminsketch_test.go b/internal/eval/countminsketch_test.go index 6c823f655..2a6b4640c 100644 --- a/internal/eval/countminsketch_test.go +++ b/internal/eval/countminsketch_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/deque.go b/internal/eval/deque.go index 2bf8c7d65..27ef1115c 100644 --- a/internal/eval/deque.go +++ b/internal/eval/deque.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/deque_test.go b/internal/eval/deque_test.go index 8788aacfe..91472cc5f 100644 --- a/internal/eval/deque_test.go +++ b/internal/eval/deque_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval_test import ( diff --git a/internal/eval/dump_restore.go b/internal/eval/dump_restore.go index 7049cdd2b..cbdf118a2 100644 --- a/internal/eval/dump_restore.go +++ b/internal/eval/dump_restore.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/eval.go b/internal/eval/eval.go index c571bd6a0..0caa2cb2a 100644 --- a/internal/eval/eval.go +++ b/internal/eval/eval.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/eval_test.go b/internal/eval/eval_test.go index 284f8431e..07c553736 100644 --- a/internal/eval/eval_test.go +++ b/internal/eval/eval_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/execute.go b/internal/eval/execute.go index 4824a67bb..1d1750ab0 100644 --- a/internal/eval/execute.go +++ b/internal/eval/execute.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/geo/geo.go b/internal/eval/geo/geo.go index 6db40eaf8..87e8a049b 100644 --- a/internal/eval/geo/geo.go +++ b/internal/eval/geo/geo.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package geo import ( diff --git a/internal/eval/hmap.go b/internal/eval/hmap.go index ccc507577..c4276d83d 100644 --- a/internal/eval/hmap.go +++ b/internal/eval/hmap.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/hmap_test.go b/internal/eval/hmap_test.go index 1e30be0a0..8c0a63d0e 100644 --- a/internal/eval/hmap_test.go +++ b/internal/eval/hmap_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/main_test.go b/internal/eval/main_test.go index bd6dac9c1..fac979abb 100644 --- a/internal/eval/main_test.go +++ b/internal/eval/main_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval_test import ( diff --git a/internal/eval/sortedset/sorted_set.go b/internal/eval/sortedset/sorted_set.go index 5b4435c3f..54dc857aa 100644 --- a/internal/eval/sortedset/sorted_set.go +++ b/internal/eval/sortedset/sorted_set.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sortedset import ( diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index 8583cedad..b32627075 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/type_asserts.go b/internal/eval/type_asserts.go index ef159ffba..8dc55f7f8 100644 --- a/internal/eval/type_asserts.go +++ b/internal/eval/type_asserts.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval // IsInt64 checks if the variable is of type int64. diff --git a/internal/eval/type_bloomfilter.go b/internal/eval/type_bloomfilter.go index a5a269f39..d255d05f1 100644 --- a/internal/eval/type_bloomfilter.go +++ b/internal/eval/type_bloomfilter.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/type_string.go b/internal/eval/type_string.go index 8ab3f9938..66a87c4c5 100644 --- a/internal/eval/type_string.go +++ b/internal/eval/type_string.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/eval/type_string_test.go b/internal/eval/type_string_test.go index 57230ff89..9fb723780 100644 --- a/internal/eval/type_string_test.go +++ b/internal/eval/type_string_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package eval import ( diff --git a/internal/id/id.go b/internal/id/id.go index 2837960b2..879b4a95b 100644 --- a/internal/id/id.go +++ b/internal/id/id.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package id import ( diff --git a/internal/id/id_test.go b/internal/id/id_test.go index 4b1cd3aa5..11e673a26 100644 --- a/internal/id/id_test.go +++ b/internal/id/id_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package id import ( diff --git a/internal/iomultiplexer/constants.go b/internal/iomultiplexer/constants.go index 308e39263..990116c13 100644 --- a/internal/iomultiplexer/constants.go +++ b/internal/iomultiplexer/constants.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iomultiplexer const ( diff --git a/internal/iomultiplexer/epoll_linux.go b/internal/iomultiplexer/epoll_linux.go index 4db842979..a760d357b 100644 --- a/internal/iomultiplexer/epoll_linux.go +++ b/internal/iomultiplexer/epoll_linux.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iomultiplexer import ( diff --git a/internal/iomultiplexer/errors.go b/internal/iomultiplexer/errors.go index 2cacdeb45..04e06e45f 100644 --- a/internal/iomultiplexer/errors.go +++ b/internal/iomultiplexer/errors.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iomultiplexer import "errors" diff --git a/internal/iomultiplexer/interface.go b/internal/iomultiplexer/interface.go index 529ba587a..b69717776 100644 --- a/internal/iomultiplexer/interface.go +++ b/internal/iomultiplexer/interface.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iomultiplexer import "time" diff --git a/internal/iomultiplexer/kqueue_darwin.go b/internal/iomultiplexer/kqueue_darwin.go index aa6939cb1..3373c6d89 100644 --- a/internal/iomultiplexer/kqueue_darwin.go +++ b/internal/iomultiplexer/kqueue_darwin.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iomultiplexer import ( diff --git a/internal/iomultiplexer/types.go b/internal/iomultiplexer/types.go index 392ce76f0..1bc820136 100644 --- a/internal/iomultiplexer/types.go +++ b/internal/iomultiplexer/types.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iomultiplexer // Event is a platform independent representation of a subscribe event diff --git a/internal/iomultiplexer/types_darwin.go b/internal/iomultiplexer/types_darwin.go index d9fe4ff4c..dc839cfa9 100644 --- a/internal/iomultiplexer/types_darwin.go +++ b/internal/iomultiplexer/types_darwin.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iomultiplexer import ( diff --git a/internal/iomultiplexer/types_linux.go b/internal/iomultiplexer/types_linux.go index c34c7b5f1..7821dff73 100644 --- a/internal/iomultiplexer/types_linux.go +++ b/internal/iomultiplexer/types_linux.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iomultiplexer import ( diff --git a/internal/iothread/cmd_compose.go b/internal/iothread/cmd_compose.go index 475269452..081871f47 100644 --- a/internal/iothread/cmd_compose.go +++ b/internal/iothread/cmd_compose.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iothread import ( diff --git a/internal/iothread/cmd_custom.go b/internal/iothread/cmd_custom.go index 39dc32304..5dd568a92 100644 --- a/internal/iothread/cmd_custom.go +++ b/internal/iothread/cmd_custom.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iothread import ( diff --git a/internal/iothread/cmd_decompose.go b/internal/iothread/cmd_decompose.go index d09196d88..0ba439aa3 100644 --- a/internal/iothread/cmd_decompose.go +++ b/internal/iothread/cmd_decompose.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iothread import ( diff --git a/internal/iothread/cmd_meta.go b/internal/iothread/cmd_meta.go index c740bae25..a72e56fd9 100644 --- a/internal/iothread/cmd_meta.go +++ b/internal/iothread/cmd_meta.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iothread import ( diff --git a/internal/iothread/cmd_preprocess.go b/internal/iothread/cmd_preprocess.go index 0bacdc8b5..b5116622f 100644 --- a/internal/iothread/cmd_preprocess.go +++ b/internal/iothread/cmd_preprocess.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iothread import ( diff --git a/internal/iothread/iothread.go b/internal/iothread/iothread.go index 6aab5120f..5188ccdc6 100644 --- a/internal/iothread/iothread.go +++ b/internal/iothread/iothread.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iothread import ( diff --git a/internal/iothread/manager.go b/internal/iothread/manager.go index 573117929..3cf95eaed 100644 --- a/internal/iothread/manager.go +++ b/internal/iothread/manager.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package iothread import ( diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 7ba1eecc9..08e24941a 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package logger import ( diff --git a/internal/logger/zerolog.go b/internal/logger/zerolog.go index 90d71864f..21d6e7f55 100644 --- a/internal/logger/zerolog.go +++ b/internal/logger/zerolog.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package logger import ( diff --git a/internal/object/deep_copy.go b/internal/object/deep_copy.go index 0e211be9f..6dcdec74a 100644 --- a/internal/object/deep_copy.go +++ b/internal/object/deep_copy.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package object import ( diff --git a/internal/object/object.go b/internal/object/object.go index 24c8527a5..43e6f8982 100644 --- a/internal/object/object.go +++ b/internal/object/object.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package object // Obj represents a basic object structure that includes metadata about the object diff --git a/internal/object/typeencoding.go b/internal/object/typeencoding.go index 8934fe710..4a75e3ceb 100644 --- a/internal/object/typeencoding.go +++ b/internal/object/typeencoding.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package object import ( diff --git a/internal/observability/constants.go b/internal/observability/constants.go index 78f59f962..d4860f109 100644 --- a/internal/observability/constants.go +++ b/internal/observability/constants.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package observability const linux = "linux" diff --git a/internal/observability/hardware.go b/internal/observability/hardware.go index 01042d244..406991f17 100644 --- a/internal/observability/hardware.go +++ b/internal/observability/hardware.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package observability import ( diff --git a/internal/observability/instance.go b/internal/observability/instance.go index 7b9eef941..6c83a3649 100644 --- a/internal/observability/instance.go +++ b/internal/observability/instance.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package observability import ( diff --git a/internal/observability/ping.go b/internal/observability/ping.go index 7ba4e3f69..84830909d 100644 --- a/internal/observability/ping.go +++ b/internal/observability/ping.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package observability import ( diff --git a/internal/ops/store_op.go b/internal/ops/store_op.go index b151066e9..376223a00 100644 --- a/internal/ops/store_op.go +++ b/internal/ops/store_op.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package ops import ( diff --git a/internal/querymanager/query_manager.go b/internal/querymanager/query_manager.go index 232a99622..e9fa64cee 100644 --- a/internal/querymanager/query_manager.go +++ b/internal/querymanager/query_manager.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package querymanager import ( diff --git a/internal/querymanager/watch_response.go b/internal/querymanager/watch_response.go index b28861235..13ad8fde4 100644 --- a/internal/querymanager/watch_response.go +++ b/internal/querymanager/watch_response.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package querymanager // CreatePushResponse creates a push response. Push responses refer to messages that the server sends to clients without diff --git a/internal/regex/regex.go b/internal/regex/regex.go index 5e2c8fb55..5f24e7179 100644 --- a/internal/regex/regex.go +++ b/internal/regex/regex.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package regex // WildCardMatch checks if the key matches the pattern using * and ? as wildcards using two pointer approach diff --git a/internal/regex/regex_test.go b/internal/regex/regex_test.go index 456cd39a3..5bd6075cf 100644 --- a/internal/regex/regex_test.go +++ b/internal/regex/regex_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package regex import ( diff --git a/internal/server/abstractserver/abstract_server.go b/internal/server/abstractserver/abstract_server.go index e2d9d91bb..678462737 100644 --- a/internal/server/abstractserver/abstract_server.go +++ b/internal/server/abstractserver/abstract_server.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package abstractserver import "context" diff --git a/internal/server/httpws/httpResp.go b/internal/server/httpws/httpResp.go index 10f77ee76..eda3bf275 100644 --- a/internal/server/httpws/httpResp.go +++ b/internal/server/httpws/httpResp.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package httpws const ( diff --git a/internal/server/httpws/httpServer.go b/internal/server/httpws/httpServer.go index f04c42aec..ab24bce51 100644 --- a/internal/server/httpws/httpServer.go +++ b/internal/server/httpws/httpServer.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package httpws import ( diff --git a/internal/server/httpws/redisCmdAdapter.go b/internal/server/httpws/redisCmdAdapter.go index 577a73e68..87286679e 100644 --- a/internal/server/httpws/redisCmdAdapter.go +++ b/internal/server/httpws/redisCmdAdapter.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package httpws import ( diff --git a/internal/server/httpws/redisCmdAdapter_test.go b/internal/server/httpws/redisCmdAdapter_test.go index 091b8bbc6..23207c468 100644 --- a/internal/server/httpws/redisCmdAdapter_test.go +++ b/internal/server/httpws/redisCmdAdapter_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package httpws import ( diff --git a/internal/server/httpws/websocketServer.go b/internal/server/httpws/websocketServer.go index bc090ff2b..89e8ed4a1 100644 --- a/internal/server/httpws/websocketServer.go +++ b/internal/server/httpws/websocketServer.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package httpws import ( diff --git a/internal/server/resp/server.go b/internal/server/resp/server.go index 51e205979..9a23184dc 100644 --- a/internal/server/resp/server.go +++ b/internal/server/resp/server.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package resp import ( diff --git a/internal/server/utils/array.go b/internal/server/utils/array.go index 1b2d83474..3126ba6ab 100644 --- a/internal/server/utils/array.go +++ b/internal/server/utils/array.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils import "reflect" diff --git a/internal/server/utils/bitfield.go b/internal/server/utils/bitfield.go index bf5f389fc..cc91ddf06 100644 --- a/internal/server/utils/bitfield.go +++ b/internal/server/utils/bitfield.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils import ( diff --git a/internal/server/utils/boolToInt.go b/internal/server/utils/boolToInt.go index f7cc55313..addf94bd9 100644 --- a/internal/server/utils/boolToInt.go +++ b/internal/server/utils/boolToInt.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils func BoolToInt(b bool) int { diff --git a/internal/server/utils/constants.go b/internal/server/utils/constants.go index 53a3137df..5a1f90903 100644 --- a/internal/server/utils/constants.go +++ b/internal/server/utils/constants.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils const ( diff --git a/internal/server/utils/floatToInt.go b/internal/server/utils/floatToInt.go index aa4560a25..17bc306c2 100644 --- a/internal/server/utils/floatToInt.go +++ b/internal/server/utils/floatToInt.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils func IsFloatToIntPossible(value float64) (int, bool) { diff --git a/internal/server/utils/json.go b/internal/server/utils/json.go index 454253f5f..539a9b1b1 100644 --- a/internal/server/utils/json.go +++ b/internal/server/utils/json.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils // This method returns the path, and a boolean value telling if the path provided follows Legacy Path Syntax or JSONPath syntax. diff --git a/internal/server/utils/jsontype.go b/internal/server/utils/jsontype.go index f7e9d05cb..bb6026d8c 100644 --- a/internal/server/utils/jsontype.go +++ b/internal/server/utils/jsontype.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils func GetJSONFieldType(v interface{}) string { diff --git a/internal/server/utils/jsontype_test.go b/internal/server/utils/jsontype_test.go index 768568fe7..1a305f91c 100644 --- a/internal/server/utils/jsontype_test.go +++ b/internal/server/utils/jsontype_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils import ( diff --git a/internal/server/utils/round.go b/internal/server/utils/round.go index 467c01eab..95806924d 100644 --- a/internal/server/utils/round.go +++ b/internal/server/utils/round.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils import "math" diff --git a/internal/server/utils/time.go b/internal/server/utils/time.go index 88fd2949f..7ed4a83dd 100644 --- a/internal/server/utils/time.go +++ b/internal/server/utils/time.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package utils import "time" diff --git a/internal/shard/shard_manager.go b/internal/shard/shard_manager.go index a3835b416..2ac77b798 100644 --- a/internal/shard/shard_manager.go +++ b/internal/shard/shard_manager.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package shard import ( diff --git a/internal/shard/shard_thread.go b/internal/shard/shard_thread.go index 313e3e4d5..3cdce0e5d 100644 --- a/internal/shard/shard_thread.go +++ b/internal/shard/shard_thread.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package shard import ( diff --git a/internal/sql/constants.go b/internal/sql/constants.go index 874f76076..422e6bcff 100644 --- a/internal/sql/constants.go +++ b/internal/sql/constants.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sql const ( diff --git a/internal/sql/dsql.go b/internal/sql/dsql.go index 133ab3a41..0296810dc 100644 --- a/internal/sql/dsql.go +++ b/internal/sql/dsql.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sql import ( diff --git a/internal/sql/dsql_test.go b/internal/sql/dsql_test.go index 0008c3fc5..5d8b98879 100644 --- a/internal/sql/dsql_test.go +++ b/internal/sql/dsql_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sql import ( diff --git a/internal/sql/executerbechmark_test.go b/internal/sql/executerbechmark_test.go index 61b4b00c5..9f88b8775 100644 --- a/internal/sql/executerbechmark_test.go +++ b/internal/sql/executerbechmark_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sql_test import ( diff --git a/internal/sql/executor.go b/internal/sql/executor.go index c85758d27..c538fce56 100644 --- a/internal/sql/executor.go +++ b/internal/sql/executor.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sql import ( diff --git a/internal/sql/executor_test.go b/internal/sql/executor_test.go index 2dd52d798..e4af51528 100644 --- a/internal/sql/executor_test.go +++ b/internal/sql/executor_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sql_test import ( diff --git a/internal/sql/fingerprint.go b/internal/sql/fingerprint.go index 5bcf5391a..6ee9150b0 100644 --- a/internal/sql/fingerprint.go +++ b/internal/sql/fingerprint.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sql import ( diff --git a/internal/sql/fingerprint_test.go b/internal/sql/fingerprint_test.go index 7f3897fae..b094b003b 100644 --- a/internal/sql/fingerprint_test.go +++ b/internal/sql/fingerprint_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package sql import ( diff --git a/internal/store/aof.go b/internal/store/aof.go index 7b63f6c23..681dcb6f2 100644 --- a/internal/store/aof.go +++ b/internal/store/aof.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store import ( diff --git a/internal/store/aof_test.go b/internal/store/aof_test.go index 7936de95a..92880eb38 100644 --- a/internal/store/aof_test.go +++ b/internal/store/aof_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store import ( diff --git a/internal/store/batchevictionlru.go b/internal/store/batchevictionlru.go index 5380f9d20..4cfecda45 100644 --- a/internal/store/batchevictionlru.go +++ b/internal/store/batchevictionlru.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store import ( diff --git a/internal/store/batchevictionlru_test.go b/internal/store/batchevictionlru_test.go index 3d2ed333e..655d00d6c 100644 --- a/internal/store/batchevictionlru_test.go +++ b/internal/store/batchevictionlru_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store import ( diff --git a/internal/store/constants.go b/internal/store/constants.go index b48d9191a..1c2e8d95a 100644 --- a/internal/store/constants.go +++ b/internal/store/constants.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store const ( diff --git a/internal/store/eviction.go b/internal/store/eviction.go index f68205182..a6d56cb27 100644 --- a/internal/store/eviction.go +++ b/internal/store/eviction.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store import ( diff --git a/internal/store/expire.go b/internal/store/expire.go index 60181ee42..077591237 100644 --- a/internal/store/expire.go +++ b/internal/store/expire.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store import ( diff --git a/internal/store/expire_test.go b/internal/store/expire_test.go index 91b371cf9..2d9bdbbb8 100644 --- a/internal/store/expire_test.go +++ b/internal/store/expire_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store import ( diff --git a/internal/store/store.go b/internal/store/store.go index 6bb18aecb..f8b2726b6 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store import ( diff --git a/internal/store/store_options.go b/internal/store/store_options.go index f02b23282..3176ea3ce 100644 --- a/internal/store/store_options.go +++ b/internal/store/store_options.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package store type PutOptions struct { diff --git a/internal/wal/wal.go b/internal/wal/wal.go index ca251560e..4fdbfb93e 100644 --- a/internal/wal/wal.go +++ b/internal/wal/wal.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package wal import ( diff --git a/internal/wal/wal.pb.go b/internal/wal/wal.pb.go index 4d82bcec8..30757ce80 100644 --- a/internal/wal/wal.pb.go +++ b/internal/wal/wal.pb.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 diff --git a/internal/wal/wal.proto b/internal/wal/wal.proto index 87e88e72d..ef95c8585 100644 --- a/internal/wal/wal.proto +++ b/internal/wal/wal.proto @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + syntax = "proto3"; package wal; diff --git a/internal/wal/wal_aof.go b/internal/wal/wal_aof.go index fe0ca7c34..e338a793b 100644 --- a/internal/wal/wal_aof.go +++ b/internal/wal/wal_aof.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package wal import ( diff --git a/internal/wal/wal_null.go b/internal/wal/wal_null.go index c4a58ccc9..b0c9d3744 100644 --- a/internal/wal/wal_null.go +++ b/internal/wal/wal_null.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package wal import ( diff --git a/internal/wal/wal_sqlite.go b/internal/wal/wal_sqlite.go index 5805667d9..677019bd1 100644 --- a/internal/wal/wal_sqlite.go +++ b/internal/wal/wal_sqlite.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package wal import ( diff --git a/internal/wal/wal_test.go b/internal/wal/wal_test.go index b3ee707e3..528913de4 100644 --- a/internal/wal/wal_test.go +++ b/internal/wal/wal_test.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package wal_test import ( diff --git a/internal/watchmanager/watch_manager.go b/internal/watchmanager/watch_manager.go index 577f171c1..99eda75c9 100644 --- a/internal/watchmanager/watch_manager.go +++ b/internal/watchmanager/watch_manager.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package watchmanager import ( diff --git a/main.go b/main.go index 0eea883a5..9a21e18a1 100644 --- a/main.go +++ b/main.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package main import ( diff --git a/mocks/slog_noop.go b/mocks/slog_noop.go index f8dae98b3..5866fe5de 100644 --- a/mocks/slog_noop.go +++ b/mocks/slog_noop.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package mocks import ( diff --git a/testutils/json.go b/testutils/json.go index 431933b8e..89fe75d88 100644 --- a/testutils/json.go +++ b/testutils/json.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package testutils import ( diff --git a/testutils/parsecommand.go b/testutils/parsecommand.go index c1a94f59e..2a6c4c8c4 100644 --- a/testutils/parsecommand.go +++ b/testutils/parsecommand.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package testutils import ( diff --git a/testutils/slices.go b/testutils/slices.go index efa284c03..acc9f4e0d 100644 --- a/testutils/slices.go +++ b/testutils/slices.go @@ -1,3 +1,19 @@ +// This file is part of DiceDB. +// Copyright (C) 2024 DiceDB (dicedb.io). +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + package testutils // UnorderedEqual compares two slices of interfaces and returns true if they From 45f7f559d0b947d4030e1c8881bbb00d138b5b28 Mon Sep 17 00:00:00 2001 From: Jyotinder Date: Sat, 14 Dec 2024 22:02:05 +0530 Subject: [PATCH 19/25] LICENSE --- LICENSE | 713 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 632 insertions(+), 81 deletions(-) diff --git a/LICENSE b/LICENSE index d710b1eb2..bae94e189 100644 --- a/LICENSE +++ b/LICENSE @@ -1,110 +1,661 @@ -``` -Business Source License 1.1 + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 -Parameters + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. -Licensor: Arpit Bhayani. -Licensed Work: DiceDB 0.x and 1.x - The Licensed Work is (c) 2024 Arpit Bhayani. -Additional Use Grant: You may make use of the Licensed Work, provided that - you may not use the Licensed Work for a Database - Service. + Preamble - A “Database Service” is a commercial offering that - allows third parties (other than your employees and - contractors) to access the functionality of the - Licensed Work by creating tables whose schemas are - controlled by such third parties. + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. -Change Date: 2028-04-01 + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. -Change License: Apache License, Version 2.0 + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. -Notice + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. -The Business Source License (this document, or the “License”) is not an Open -Source license. However, the Licensed Work will eventually be made available -under an Open Source License, as stated in this License. + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. ------------------------------------------------------------------------------ + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. -Business Source License 1.1 + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. -Terms + The precise terms and conditions for copying, distribution and +modification follow. -The Licensor hereby grants you the right to copy, modify, create derivative -works, redistribute, and make non-production use of the Licensed Work. The -Licensor may make an Additional Use Grant, above, permitting limited -production use. + TERMS AND CONDITIONS -Effective on the Change Date, or the fourth anniversary of the first publicly -available distribution of a specific version of the Licensed Work under this -License, whichever comes first, the Licensor hereby grants you rights under -the terms of the Change License, and the rights granted in the paragraph -above terminate. + 0. Definitions. -If your use of the Licensed Work does not comply with the requirements -currently in effect as described in this License, you must purchase a -commercial license from the Licensor, its affiliated entities, or authorized -resellers, or you must refrain from using the Licensed Work. + "This License" refers to version 3 of the GNU Affero General Public License. -All copies of the original and modified Licensed Work, and derivative works -of the Licensed Work, are subject to this License. This License applies -separately for each version of the Licensed Work and the Change Date may vary -for each version of the Licensed Work released by Licensor. + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. -You must conspicuously display this License on each original or modified copy -of the Licensed Work. If you receive the Licensed Work in original or -modified form from a third party, the terms and conditions set forth in this -License apply to your use of that work. + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. -Any use of the Licensed Work in violation of this License will automatically -terminate your rights under this License for the current and all other -versions of the Licensed Work. + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. -This License does not grant you any right in any trademark or logo of -Licensor or its affiliates (provided that you may use a trademark or logo of -Licensor as expressly required by this License). + A "covered work" means either the unmodified Program or a work based +on the Program. -TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON -AN “AS IS” BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, -EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND -TITLE. + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. -Covenants of Licensor + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. -In consideration of the right to use this License’s text and the “Business -Source License” name and trademark, Licensor covenants to all -other recipients of the licensed work to be provided by Licensor: + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. -1. To specify as the Change License the Apache License, Version 2.0 or any later version, - or a license that is compatible with Apache License, Version 2.0 or a later version, - where “compatible” means that software provided under the Change License can - be included in a program with software provided under Apache License, Version 2.0 or a - later version. Licensor may specify additional Change Licenses without - limitation. + 1. Source Code. -2. To either: (a) specify an additional grant of rights to use that does not - impose any additional restriction on the right granted in this License, as - the Additional Use Grant; or (b) insert the text “None”. + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. -3. To specify a Change Date. + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. -4. Not to modify this License in any other way. -``` + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. ---- + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. -``` -Copyright (c) 2006-2020, Salvatore Sanfilippo -All rights reserved. + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + The Corresponding Source for a work in source code form is that +same work. - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - * Neither the name of Redis nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + 2. Basic Permissions. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -``` + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. \ No newline at end of file From c3d5970f606ccc132d8e093ff57b0291ecaed1f7 Mon Sep 17 00:00:00 2001 From: Jyotinder Singh Date: Sat, 14 Dec 2024 22:13:29 +0530 Subject: [PATCH 20/25] Improves SET command implementation (#1371) --- internal/eval/store_eval.go | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/internal/eval/store_eval.go b/internal/eval/store_eval.go index b32627075..1ebe929c2 100644 --- a/internal/eval/store_eval.go +++ b/internal/eval/store_eval.go @@ -217,7 +217,11 @@ func evalSET(args []string, store *dstore.Store) *EvalResponse { var oldVal *interface{} key, value = args[0], args[1] - _, oType := getRawStringOrInt(value) + storedValue, oType := getRawStringOrInt(value) + + if oType != object.ObjTypeInt && oType != object.ObjTypeString { + return makeEvalError(diceerrors.ErrUnsupportedEncoding(int(oType))) + } for i := 2; i < len(args); i++ { arg := strings.ToUpper(args[i]) @@ -310,17 +314,6 @@ func evalSET(args []string, store *dstore.Store) *EvalResponse { } } - // Cast the value properly based on the encoding type - var storedValue interface{} - switch oType { - case object.ObjTypeInt: - storedValue, _ = strconv.ParseInt(value, 10, 64) - case object.ObjTypeString: - storedValue = value - default: - return makeEvalError(diceerrors.ErrUnsupportedEncoding(int(oType))) - } - // putting the k and value in a Hash Table store.Put(key, store.NewObj(storedValue, exDurationMs, oType), dstore.WithKeepTTL(keepttl)) if oldVal != nil { From 23c7b48a798e5c55852ff81f65966b7cd8fc1b60 Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Sat, 14 Dec 2024 23:10:00 +0530 Subject: [PATCH 21/25] Publishing DiceDB is now open source blog (#1373) * Communicating Open Source * DiceDB is Open Source Blog --- README.md | 2 +- docs/public/funding.json | 4 +- docs/src/components/Hero.astro | 4 +- .../src/content/blog/dicedb-is-open-source.md | 79 +++++++++++++++++++ .../content/docs/get-started/installation.mdx | 2 +- docs/src/pages/community/index.astro | 2 +- docs/src/pages/index.astro | 13 ++- docs/src/pages/team.astro | 8 +- 8 files changed, 102 insertions(+), 12 deletions(-) create mode 100644 docs/src/content/blog/dicedb-is-open-source.md diff --git a/README.md b/README.md index 2335c52bb..e4c4ba3aa 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ DiceDB ![Docs](https://img.shields.io/badge/docs-00A1FF?style=flat-square) discord community -DiceDB is a redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware. +DiceDB is an open source, redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware. We are looking for Early Design Partners, so, if you want to evaluate DiceDB, [block our calendar](https://cal.com/dicedb-arpit). always up for a chat. diff --git a/docs/public/funding.json b/docs/public/funding.json index 703ed0d2f..c8b6eba21 100644 --- a/docs/public/funding.json +++ b/docs/public/funding.json @@ -6,7 +6,7 @@ "name": "DiceDB", "email": "arpit@dicedb.io", "phone": "", - "description": "DiceDB is a redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware.", + "description": "DiceDB is an open source, redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware.", "webpageUrl": { "url": "https://dicedb.io" } @@ -15,7 +15,7 @@ { "guid": "dicedb", "name": "DiceDB", - "description": "DiceDB is a redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware.", + "description": "DiceDB is an open source, redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware.", "webpageUrl": { "url": "https://dicedb.io" }, diff --git a/docs/src/components/Hero.astro b/docs/src/components/Hero.astro index 9dd3d46c8..b4715ecf7 100644 --- a/docs/src/components/Hero.astro +++ b/docs/src/components/Hero.astro @@ -8,8 +8,8 @@ import { Github } from "lucide-astro";

    a super cache;

    - DiceDB is a redis-compliant, reactive, scalable, highly available, - unified cache optimized for modern hardware + DiceDB is an open source, redis-compliant, reactive, scalable, highly + available, unified cache optimized for modern hardware *

    diff --git a/docs/src/content/blog/dicedb-is-open-source.md b/docs/src/content/blog/dicedb-is-open-source.md new file mode 100644 index 000000000..6bc1f3d61 --- /dev/null +++ b/docs/src/content/blog/dicedb-is-open-source.md @@ -0,0 +1,79 @@ +--- +title: "DiceDB is now open source" +description: "Since the inception of DiceDB, our vision has always been rooted in +building a high-performance caching backbone for modern architecture. Today, we are thrilled to announce that DiceDB +is now open source under the GNU Affero General Public License (AGPL) 3.0. This marks a significant milestone in our journey - one that reflects both our technical clarity and our commitment to the open-source ethos." +published_at: 2024-12-14 +author: arpit +--- + +Since the inception of DiceDB, [our](dicedb.io/team) vision has always been rooted in +building a high-performance caching backbone for modern architecture. Today, we are thrilled to announce that DiceDB +is now open source under the [GNU Affero General Public License (AGPL) 3.0](https://github.com/dicedb/dice?tab=AGPL-3.0-1-ov-file#readme). +This marks a significant milestone in our journey - one that reflects both our technical clarity and our commitment to the open-source ethos. + +## Why We Switched from BSL to GNU AGPL 3.0 + +In the early days of DiceDB, we explored a [Business Source License (BSL)](https://en.wikipedia.org/wiki/Business_Source_License) +to balance monetization and community engagement. However, as our product evolved, +so did our understanding of its core mission. + +DiceDB isn't just another in-memory database; it's the foundation for the next generation +of applications. By streamlining our +technical and business priorities, we realized that the +AGPL 3.0 license better aligns with where we are headed — an open, +collaborative ecosystem for the future of caching infrastructure. + +As engineers, we believe in removing artificial barriers that gatekeep innovation. +The AGPL's principles align deeply with our philosophy — software should be free +to use, inspect, and improve. By adopting this license, we're doubling down +on accessibility and transparency. We believe that great infrastructure +shouldn't be proprietary; it should be a shared foundation for the ecosystem to build upon. + +The AGPL license removes ambiguity around our open-source intent, signaling +to developers and organizations alike that DiceDB is here to stay as a +truly open technology. This clarity encourages collaboration, enabling developers and engineers to +confidently build, adapt, and contribute back to the project. +Whether it's improving availability, or performance, or even building advanced connectors, +every contribution will strengthen DiceDB for everyone. + +Additionally, the AGPL is designed to ensure fairness. It prevents +the “freeloading” problem — where companies take open-source software, modify it, +and deploy it as a proprietary service without contributing back. +With the AGPL, any modifications made while running DiceDB as a +service must also be shared under the same license. This keeps the playing +field level, ensuring that innovation remains a collaborative effort rather than being siloed. + +## What This Means for Developers + +Developers now have the freedom to innovate with DiceDB. You +can freely use DiceDB, modify it, and build applications tailored to your specific needs. +By sharing improvements under the AGPL, you're contributing to a broader ecosystem that evolves +together. Every line of code written to build DiceDB is open for inspection, learning, and improvement. + +## A Glimpse Into the Future + +This license switch isn't just a symbolic move; it's a strategic decision. Our roadmap +includes multi-tenancy, horizontal scalability, infra abstraction, reactivity, +observability, easy cluster management, and a capable control plane with high observability. + +We're also advancing persistence, fault tolerance, query capabilities, and data structure support. +Additionally, lightning-fast replica creations will extend DiceDB's capabilities to handle production-grade workloads +with resumability and reliability. + +By going fully open-source under AGPL 3.0, we're inviting the +community to join us in building the caching backbone that powers the next generation of +applications. Together, we can push the boundaries of what's possible. + +We're excited about this next chapter and can't wait to see how you +use and contribute to DiceDB. Here's [the repository](https://github.com/dicedb/dice), +let's build the future of real-time data together. + +## Things you will find interesting + +As you explore DiceDB, you’ll uncover several intriguing facets of our journey. +Dive into our [community hub](/community) to learn more about our vibrant community and browse through notes from our weekly calls. +If performance excites you, don’t miss our [benchmarks](/benchmarks) showcasing how DiceDB achieves 10x better throughput +by leveraging the full potential of the underlying hardware. + +At our core, we’re just a [group of passionate engineers](/team) pursuing an ambitious vision; join us and help shape and build the caching backbone of modern architecture. diff --git a/docs/src/content/docs/get-started/installation.mdx b/docs/src/content/docs/get-started/installation.mdx index 8ba500b4e..7c0e8a11a 100644 --- a/docs/src/content/docs/get-started/installation.mdx +++ b/docs/src/content/docs/get-started/installation.mdx @@ -5,7 +5,7 @@ sidebar: order: 1 --- -DiceDB is a redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware. +DiceDB is an open source, redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware. We are looking for Early Design Partners, so, if you want to evaluate DiceDB, [block our calendar](https://cal.com/dicedb-arpit). always up for a chat. diff --git a/docs/src/pages/community/index.astro b/docs/src/pages/community/index.astro index 588b386c5..7d95ba780 100644 --- a/docs/src/pages/community/index.astro +++ b/docs/src/pages/community/index.astro @@ -41,7 +41,7 @@ const callLink = "https://meet.google.com/qdf-pfkb-ckm";

    Weekly calls

    - We need every Thursday at 19:00 IST to discuss what we did and what we + We meet every Thursday at 19:00 IST to discuss what we did and what we plan to do. The meeting is open to everyone, and you can join the call by clicking the button below.

    diff --git a/docs/src/pages/index.astro b/docs/src/pages/index.astro index 4aa1d31e0..a2ab30016 100644 --- a/docs/src/pages/index.astro +++ b/docs/src/pages/index.astro @@ -12,7 +12,7 @@ const recentBlogs = blogs const title = "DiceDB - a super cache;"; const description = - "DiceDB is a redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware."; + "DiceDB is an open source, redis-compliant, reactive, scalable, highly available, unified cache optimized for modern hardware."; --- @@ -20,6 +20,13 @@ const description =

    DiceDB is

    +

    + and we aim to be the high-performance caching backbone for modern + architecture. +

    DICEDB BLOG

    diff --git a/docs/src/pages/team.astro b/docs/src/pages/team.astro index a2df83d4e..bd12ae3c6 100644 --- a/docs/src/pages/team.astro +++ b/docs/src/pages/team.astro @@ -36,10 +36,10 @@ const description = highly available, unified cache optimized for modern hardware.


    -
    +
    { pmc.map((member) => ( -
    +
    {member.data.name}

    {member.data.name.split(" ").map((char) => ( @@ -63,10 +63,10 @@ const description = quality of the codebase along with working on critical features and improvements.

    -
    +
    { committers.map((member) => ( -
    +
    {member.data.name}

    {member.data.name}

    Date: Sat, 14 Dec 2024 23:24:26 +0530 Subject: [PATCH 22/25] Updating OG Image --- docs/public/img/general-cover.png | Bin 67034 -> 57626 bytes .../src/content/blog/dicedb-is-open-source.md | 14 ++++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/public/img/general-cover.png b/docs/public/img/general-cover.png index 8ff6f767b3c09dbfbbf244ac4dd79f8d7cfbb659..ce6800471544aa63e3026cb57c15a8fe26c70f82 100644 GIT binary patch literal 57626 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 aaYdoI``de; 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 Date: Sat, 14 Dec 2024 23:30:25 +0530 Subject: [PATCH 23/25] Editing blog to keep things consistent --- docs/src/content/blog/dicedb-is-open-source.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/src/content/blog/dicedb-is-open-source.md b/docs/src/content/blog/dicedb-is-open-source.md index 12f5c5d05..ee915642f 100644 --- a/docs/src/content/blog/dicedb-is-open-source.md +++ b/docs/src/content/blog/dicedb-is-open-source.md @@ -12,7 +12,7 @@ building a high-performance caching backbone for modern architecture. Today, we is now open source under the [GNU Affero General Public License (AGPL) 3.0](https://github.com/dicedb/dice?tab=AGPL-3.0-1-ov-file#readme). This marks a significant milestone in our journey - one that reflects both our technical clarity and our commitment to the open-source ethos. -## Why We Switched from BSL to GNU AGPL 3.0 +## Why we switched In the early days of DiceDB, we explored a [Business Source License (BSL)](https://en.wikipedia.org/wiki/Business_Source_License) to balance monetization and community engagement. However, as our product evolved, @@ -44,14 +44,14 @@ With the AGPL, any modifications made while running DiceDB as a service must also be shared under the same license. This keeps the playing field level, ensuring that innovation remains a collaborative effort rather than being siloed. -## What This Means for Developers +## What this means for developers Developers now have the freedom to innovate with DiceDB. You can freely use DiceDB, modify it, and build applications tailored to your specific needs. By sharing improvements under the AGPL, you're contributing to a broader ecosystem that evolves together. Every line of code written to build DiceDB is open for inspection, learning, and improvement. -## A Glimpse Into the Future +## A glimpse into the future This license switch isn't just a symbolic move; it's a strategic decision. Our roadmap includes multi-tenancy, horizontal scalability, infrastructure abstraction, reactivity, From 0bef689dac65c36864fb1c1e6a705ffc02d8f20c Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Sun, 15 Dec 2024 00:57:31 +0530 Subject: [PATCH 24/25] Editorial changes --- .../blog/dicedb-a-reactive-database.md | 80 +++++++++++++++++++ .../src/content/blog/dicedb-is-open-source.md | 25 +++--- 2 files changed, 91 insertions(+), 14 deletions(-) create mode 100644 docs/src/content/blog/dicedb-a-reactive-database.md diff --git a/docs/src/content/blog/dicedb-a-reactive-database.md b/docs/src/content/blog/dicedb-a-reactive-database.md new file mode 100644 index 000000000..8aa2f990c --- /dev/null +++ b/docs/src/content/blog/dicedb-a-reactive-database.md @@ -0,0 +1,80 @@ +--- +title: "DiceDB, a reactive database" +description: "" +published_at: 2024-11-12 +author: arpit +--- + +In traditional databases, we query data when it's needed; a process that is simple but can become highly inefficient when large number of expensive and redundant queries are frequently fired on the database. Let's understand this by building a leaderboard. + +Imagine a traditional database that maintains a leaderboard for a competitive game or application. Here, an asynchronous flow updates the leaderboard data continuously in the database, reflecting new scores or rankings as they come in. + +Now consider the users: thousands of clients query this leaderboard every 10 seconds to get the latest rankings. Every query requires the database to compute the current leaderboard standings based on the updated data and then respond to the client with the latest results. Upon receiving the result, each client proceeds to render the leaderboard in its application, ensuring users see the current standings. + +TODO: image. + +In this setup, several issues arise: + +1. Redundant Computation: Since thousands of clients are querying the database every few seconds, the database repeatedly computes the leaderboard, even if there has been little or no change in scores. This results in substantial redundant processing, significantly taxing the database resources. + +2. High Load and Latency: The high frequency and volume of queries introduce a considerable load on the database, leading to latency. The database must allocate resources to process each query individually, slowing down response times as the number of clients scales. + +3. Increased Infrastructure Costs: To handle the high query volume, the system may require powerful hardware and extensive scaling strategies, leading to increased operational costs. + +This traditional query model is inefficient for high-read, rapidly updating data structures like leaderboards, where many clients want real-time information. This setup incurs significant resource overhead and diminishes the overall system performance, especially under heavy load. + +This is where DiceDB, a reactive database chimes in ... + +## What is a reactive database? + +The concept of a reactive database is simple, a reactive database pushes updated query results to clients as soon as the underlying data changes. DiceDB, upon detecting the change in data, automatically re-evaluates the relevant queries and immediately streams the updated result sets to all clients who have subscribed to it. + +TODO Image. + +This real-time reactivity ensures that clients always receive the latest data without the need to send repeated queries, dramatically reducing network load and latency while providing an efficient, seamless experience for data-driven applications. + +### Reactive Databases are not CDC + +One common comparison that is draw to reactive data is of CDC. Dice DB is not same as CDC. CDC is about capturing the delta of changes in data, but in DiceDB the output of the Query is streamed and it is not just a notification about the change. This makes DiceDB a truly real-time reactive database. + +## DiceDB: A Reactive Database + +**DiceDB** exemplifies the reactive database model. Designed as a Redis-compatible, in-memory, multi-threaded database, it focuses on real-time reactivity and efficiency, enabling it to handle modern application demands for both speed and scale. In DiceDB, clients can set up **query subscriptions** for specific data keys or patterns. When a value tied to a subscribed query changes, the updated result set is **pushed directly to the subscribed clients**. This push model eliminates the need for clients to continuously poll for updates. + +### How Query Subscriptions Work in DiceDB + +DiceDB's query subscription model is designed around the concept of **data-driven reactivity**: + +1. **Subscription Creation**: Clients initiate a subscription by registering a query or specific data key on DiceDB. For example, if an application wants to monitor changes to a leaderboard score, it subscribes to the relevant leaderboard key. + +2. **Data Monitoring**: DiceDB continuously monitors data for any changes affecting the subscribed queries. Unlike traditional databases, where monitoring is external and client-driven, DiceDB handles this process internally and in real time. + +3. **Automatic Query Execution on Data Changes**: When DiceDB detects a change in a subscribed key, it evaluates the relevant query automatically. This step is only triggered by a change, meaning no computational resources are used to check for updates unless necessary. + +4. **Result Streaming to Subscribed Clients**: After query evaluation, DiceDB streams the updated result set to each client that subscribed to the query. This eliminates the need for each client to independently query the database, thus reducing network traffic, CPU usage, and latency. + +### Real-World Application: Leaderboards + +To illustrate the power of DiceDB’s reactive architecture, consider the use case of a leaderboard in a gaming application: + +- In a traditional setup, if there are \( n \) users, each user might query the database every 10 seconds to see if the leaderboard has changed. This would result in \( n \) redundant queries every 10 seconds, all asking for the same information. + +- With DiceDB, each client can **subscribe** to the leaderboard key. As players’ scores change, DiceDB will automatically evaluate the leaderboard query only when a score update occurs. The updated leaderboard is then **pushed to all subscribed clients**. This approach drastically reduces the number of database operations, as DiceDB processes the query once per update instead of once per client, per interval. + +For instance, if the leaderboard updates once every 10 seconds, DiceDB would process the query once, and stream the result to all clients simultaneously. This efficiency means DiceDB can scale to support significantly larger user bases without experiencing the query-based bottlenecks seen in traditional databases. + +### Efficiency Gains and Cost Reduction + +The reactivity model provided by DiceDB offers several key benefits: + +- **Reduced Query Load**: DiceDB eliminates the need for repeated, redundant queries by moving from a client-polling approach to a server-push model. This is especially beneficial in high-read applications where many clients request the same information. + +- **Lower Latency**: With data being pushed as soon as it changes, clients receive updates faster, leading to lower latency and a more seamless user experience. + +- **Resource Savings**: By processing a query once and distributing the result to all subscribers, DiceDB significantly reduces CPU, memory, and network usage. This approach can lead to cost savings by reducing the need for scaling infrastructure to handle repetitive loads. + +### Conclusion: DiceDB and the Future of Reactive Databases + +DiceDB exemplifies a shift towards a data-reactive paradigm, where the database is not merely a repository for queries but an active participant in maintaining data synchronization with minimal client intervention. Through query subscriptions and real-time data streaming, DiceDB provides a model that can efficiently handle the demands of modern applications, enabling real-time, highly reactive user experiences at a reduced cost. + +This transition to reactivity represents a substantial evolution in database technology. As applications increasingly require real-time interactivity and scalable performance, systems like DiceDB are poised to play a critical role in powering the next generation of real-time applications. diff --git a/docs/src/content/blog/dicedb-is-open-source.md b/docs/src/content/blog/dicedb-is-open-source.md index ee915642f..3cc6ee763 100644 --- a/docs/src/content/blog/dicedb-is-open-source.md +++ b/docs/src/content/blog/dicedb-is-open-source.md @@ -2,7 +2,7 @@ title: "DiceDB is now open source" description: "Since the inception of DiceDB, our vision has always been rooted in building a high-performance caching backbone for modern architecture. Today, we are thrilled to announce that DiceDB -is now open source under the GNU Affero General Public License (AGPL) 3.0. This marks a significant milestone in our journey - one that reflects both our technical clarity and our commitment to the open-source ethos." +is now open source under the GNU Affero General Public License (AGPL) 3.0. This marks a significant milestone in our journey - one that reflects both our technical clarity and our commitment to the open source ethos." published_at: 2024-12-14 author: arpit --- @@ -10,16 +10,13 @@ author: arpit Since the inception of DiceDB, [our](dicedb.io/team) vision has always been rooted in building a high-performance caching backbone for modern architecture. Today, we are thrilled to announce that DiceDB is now open source under the [GNU Affero General Public License (AGPL) 3.0](https://github.com/dicedb/dice?tab=AGPL-3.0-1-ov-file#readme). -This marks a significant milestone in our journey - one that reflects both our technical clarity and our commitment to the open-source ethos. +This marks a significant milestone in our journey - one that reflects both our technical clarity and our commitment to the open source ethos. ## Why we switched In the early days of DiceDB, we explored a [Business Source License (BSL)](https://en.wikipedia.org/wiki/Business_Source_License) to balance monetization and community engagement. However, as our product evolved, -so did our understanding of its core mission. - -DiceDB isn't just another in-memory database; it's the foundation for the next generation -of applications. By streamlining our +so did our understanding of its core mission. By streamlining our technical and business priorities, we realized that the AGPL 3.0 license better aligns with where we are headed — an open, collaborative ecosystem for the future of caching infrastructure. @@ -30,7 +27,7 @@ to use, inspect, and improve. By adopting this license, we're doubling down on accessibility and transparency. We believe that great infrastructure shouldn't be proprietary; it should be a shared foundation for the ecosystem to build upon. -The AGPL license removes ambiguity around our open-source intent, signaling +The AGPL license removes ambiguity around our open source intent, signaling to developers and organizations alike that DiceDB is here to stay as a truly open technology. This clarity encourages collaboration, enabling developers and engineers to confidently build, adapt, and contribute back to the project. @@ -38,7 +35,7 @@ Whether it's improving availability, or performance, or even building advanced c every contribution will strengthen DiceDB for everyone. Additionally, the AGPL is designed to ensure fairness. It prevents -the “freeloading” problem — where companies take open-source software, modify it, +the "freeloading" problem — where companies take open source software, modify it, and deploy it as a proprietary service without contributing back. With the AGPL, any modifications made while running DiceDB as a service must also be shared under the same license. This keeps the playing @@ -56,14 +53,14 @@ together. Every line of code written to build DiceDB is open for inspection, lea This license switch isn't just a symbolic move; it's a strategic decision. Our roadmap includes multi-tenancy, horizontal scalability, infrastructure abstraction, reactivity, observability, persistence, fault tolerance, seamless cluster management, and a -robust control plane with high observability. +robust control plane. We are also enhancing query capabilities and data structure support to meet -the demands of AI-first applications—an approach poised to become the standard +the demands of AI-first applications - an approach poised to become the standard in the coming decade. Furthermore, lightning-fast replica creation will reinforce DiceDB's ability to handle production-grade workloads with exceptional reliability and resumability. -By going fully open-source under AGPL 3.0, we're inviting the +By going fully open source under AGPL 3.0, we're inviting the community to join us in building the caching backbone that powers the next generation of applications. Together, we can push the boundaries of what's possible. @@ -73,9 +70,9 @@ let's build the future of real-time data together. ## Things you will find interesting -As you explore DiceDB, you’ll uncover several intriguing facets of our journey. +As you explore DiceDB, you'll uncover several intriguing facets of our journey. Dive into our [community hub](/community) to learn more about our vibrant community and browse through notes from our weekly calls. -If performance excites you, don’t miss our [benchmarks](/benchmarks) showcasing how DiceDB achieves 10x better throughput +If performance excites you, don't miss our [benchmarks](/benchmarks) showcasing how DiceDB achieves 10x better throughput by leveraging the full potential of the underlying hardware. -At our core, we’re just a [group of passionate engineers](/team) pursuing an ambitious vision; join us and help shape and build the caching backbone of modern architecture. +At our core, we're just a [group of passionate engineers](/team) pursuing an ambitious vision; join us and help shape and build the caching backbone of modern architecture. From e8f2573570a8674a625c6d0612d6a071b865a6cd Mon Sep 17 00:00:00 2001 From: Arpit Bhayani Date: Sun, 15 Dec 2024 01:32:19 +0530 Subject: [PATCH 25/25] Removing unpublished blog --- .../blog/dicedb-a-reactive-database.md | 80 ------------------- 1 file changed, 80 deletions(-) delete mode 100644 docs/src/content/blog/dicedb-a-reactive-database.md diff --git a/docs/src/content/blog/dicedb-a-reactive-database.md b/docs/src/content/blog/dicedb-a-reactive-database.md deleted file mode 100644 index 8aa2f990c..000000000 --- a/docs/src/content/blog/dicedb-a-reactive-database.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "DiceDB, a reactive database" -description: "" -published_at: 2024-11-12 -author: arpit ---- - -In traditional databases, we query data when it's needed; a process that is simple but can become highly inefficient when large number of expensive and redundant queries are frequently fired on the database. Let's understand this by building a leaderboard. - -Imagine a traditional database that maintains a leaderboard for a competitive game or application. Here, an asynchronous flow updates the leaderboard data continuously in the database, reflecting new scores or rankings as they come in. - -Now consider the users: thousands of clients query this leaderboard every 10 seconds to get the latest rankings. Every query requires the database to compute the current leaderboard standings based on the updated data and then respond to the client with the latest results. Upon receiving the result, each client proceeds to render the leaderboard in its application, ensuring users see the current standings. - -TODO: image. - -In this setup, several issues arise: - -1. Redundant Computation: Since thousands of clients are querying the database every few seconds, the database repeatedly computes the leaderboard, even if there has been little or no change in scores. This results in substantial redundant processing, significantly taxing the database resources. - -2. High Load and Latency: The high frequency and volume of queries introduce a considerable load on the database, leading to latency. The database must allocate resources to process each query individually, slowing down response times as the number of clients scales. - -3. Increased Infrastructure Costs: To handle the high query volume, the system may require powerful hardware and extensive scaling strategies, leading to increased operational costs. - -This traditional query model is inefficient for high-read, rapidly updating data structures like leaderboards, where many clients want real-time information. This setup incurs significant resource overhead and diminishes the overall system performance, especially under heavy load. - -This is where DiceDB, a reactive database chimes in ... - -## What is a reactive database? - -The concept of a reactive database is simple, a reactive database pushes updated query results to clients as soon as the underlying data changes. DiceDB, upon detecting the change in data, automatically re-evaluates the relevant queries and immediately streams the updated result sets to all clients who have subscribed to it. - -TODO Image. - -This real-time reactivity ensures that clients always receive the latest data without the need to send repeated queries, dramatically reducing network load and latency while providing an efficient, seamless experience for data-driven applications. - -### Reactive Databases are not CDC - -One common comparison that is draw to reactive data is of CDC. Dice DB is not same as CDC. CDC is about capturing the delta of changes in data, but in DiceDB the output of the Query is streamed and it is not just a notification about the change. This makes DiceDB a truly real-time reactive database. - -## DiceDB: A Reactive Database - -**DiceDB** exemplifies the reactive database model. Designed as a Redis-compatible, in-memory, multi-threaded database, it focuses on real-time reactivity and efficiency, enabling it to handle modern application demands for both speed and scale. In DiceDB, clients can set up **query subscriptions** for specific data keys or patterns. When a value tied to a subscribed query changes, the updated result set is **pushed directly to the subscribed clients**. This push model eliminates the need for clients to continuously poll for updates. - -### How Query Subscriptions Work in DiceDB - -DiceDB's query subscription model is designed around the concept of **data-driven reactivity**: - -1. **Subscription Creation**: Clients initiate a subscription by registering a query or specific data key on DiceDB. For example, if an application wants to monitor changes to a leaderboard score, it subscribes to the relevant leaderboard key. - -2. **Data Monitoring**: DiceDB continuously monitors data for any changes affecting the subscribed queries. Unlike traditional databases, where monitoring is external and client-driven, DiceDB handles this process internally and in real time. - -3. **Automatic Query Execution on Data Changes**: When DiceDB detects a change in a subscribed key, it evaluates the relevant query automatically. This step is only triggered by a change, meaning no computational resources are used to check for updates unless necessary. - -4. **Result Streaming to Subscribed Clients**: After query evaluation, DiceDB streams the updated result set to each client that subscribed to the query. This eliminates the need for each client to independently query the database, thus reducing network traffic, CPU usage, and latency. - -### Real-World Application: Leaderboards - -To illustrate the power of DiceDB’s reactive architecture, consider the use case of a leaderboard in a gaming application: - -- In a traditional setup, if there are \( n \) users, each user might query the database every 10 seconds to see if the leaderboard has changed. This would result in \( n \) redundant queries every 10 seconds, all asking for the same information. - -- With DiceDB, each client can **subscribe** to the leaderboard key. As players’ scores change, DiceDB will automatically evaluate the leaderboard query only when a score update occurs. The updated leaderboard is then **pushed to all subscribed clients**. This approach drastically reduces the number of database operations, as DiceDB processes the query once per update instead of once per client, per interval. - -For instance, if the leaderboard updates once every 10 seconds, DiceDB would process the query once, and stream the result to all clients simultaneously. This efficiency means DiceDB can scale to support significantly larger user bases without experiencing the query-based bottlenecks seen in traditional databases. - -### Efficiency Gains and Cost Reduction - -The reactivity model provided by DiceDB offers several key benefits: - -- **Reduced Query Load**: DiceDB eliminates the need for repeated, redundant queries by moving from a client-polling approach to a server-push model. This is especially beneficial in high-read applications where many clients request the same information. - -- **Lower Latency**: With data being pushed as soon as it changes, clients receive updates faster, leading to lower latency and a more seamless user experience. - -- **Resource Savings**: By processing a query once and distributing the result to all subscribers, DiceDB significantly reduces CPU, memory, and network usage. This approach can lead to cost savings by reducing the need for scaling infrastructure to handle repetitive loads. - -### Conclusion: DiceDB and the Future of Reactive Databases - -DiceDB exemplifies a shift towards a data-reactive paradigm, where the database is not merely a repository for queries but an active participant in maintaining data synchronization with minimal client intervention. Through query subscriptions and real-time data streaming, DiceDB provides a model that can efficiently handle the demands of modern applications, enabling real-time, highly reactive user experiences at a reduced cost. - -This transition to reactivity represents a substantial evolution in database technology. As applications increasingly require real-time interactivity and scalable performance, systems like DiceDB are poised to play a critical role in powering the next generation of real-time applications.