Repository: DiceDB/dice
File: core/eval.go (Go)

Code before:
			if exDurationUnixMs < 0 {
				return Encode(errors.New("ERR invalid expire time in 'set' command"), false)
			}

			exDurationMs = exDurationUnixMs - time.Now().UnixMilli()
			// If the expiry time is in the past, set exDurationMs to 0
			// This will be used to signal immediate expiration
			if exDurationMs < 0 {
				exDurationMs = 0
			}
			state = Initialized

		case "XX", "xx":
			// Get the key from the hash table
			obj := Get(key)

			// if key does not exist, return RESP encoded nil
			if obj == nil {
				return RESP_NIL
			}
		case "NX", "nx":
			obj := Get(key)
			if obj != nil {
				return RESP_NIL
			}
		case "EXAT", "exat":
			i++
			if i == len(args) {
				return Encode(errors.New("ERR syntax error"), false)
			}

			exAt, err := strconv.ParseInt(args[i], 10, 64)
			if err != nil {
				return Encode(errors.New("ERR value is not an integer or out of range"), false)
			}

			currentTime := time.Now().Unix()
			if exAt <= currentTime {
				return Encode(errors.New("ERR invalid EXAT time in the past"), false)
			}

			exDurationMs = (exAt - currentTime) * 1000
		default:
			return Encode(errors.New("ERR syntax error"), false)
		}
	}

	// putting the k and value in a Hash Table
	Put(key, NewObj(value, exDurationMs, oType, oEnc))
	return RESP_OK
}

Review comment (suggestion):
Can we implementation for EXAT/PXAT inline with EX/PX, i.e. consolidate the code and handle validate that only one of the options among  EXAT/PXAT/EX/PX is provided in input. If more than one of the options are provided we should return error.

I also have a minor suggestion to make the existing code a little more clearer to read:

Adding `arg := strings.ToUpper(args[i])` before switch statement:

This makes your code a little more readable:
`case "EX", "ex", "PX", "px":`
`case "EXAT", "exat", "PXAT", "pxat":`

is reduced to
`case "EX", "PX":`
`case "EXAT", "PXAT"`

and 
`if args[i-1] == "EX" || args[i-1] == "ex" `
`if args[i-1] == "EXAT" || args[i-1] == "exat" `

can be reduced to
`if arg == "EX" {`
`if arg == "EXAT" {`

Please let me know wdyt.

Code after:

			if exDuration < 0 {
				return Encode(errors.New("ERR invalid expire time in 'set' command"), false)
			}
			
			if arg == "EXAT" {
				exDuration = exDuration * 1000
			}

			exDurationMs = exDuration - time.Now().UnixMilli()
			// If the expiry time is in the past, set exDurationMs to 0
			// This will be used to signal immediate expiration
			if exDurationMs < 0 {
				exDurationMs = 0
			}
			state = Initialized

		case "XX":
			// Get the key from the hash table
			obj := Get(key)

			// if key does not exist, return RESP encoded nil
			if obj == nil {
				return RESP_NIL
			}
		case "NX":
			obj := Get(key)
			if obj != nil {
				return RESP_NIL
			}
		default:
			return Encode(errors.New("ERR syntax error"), false)
		}
	}

	// putting the k and value in a Hash Table
	Put(key, NewObj(value, exDurationMs, oType, oEnc))
	return RESP_OK
}

// evalGET returns the value for the queried key in args
// The key should be the only param in args
// The RESP value of the key is encoded and then returned
// evalGET returns RESP_NIL if key is expired or it does not exist
func evalGET(args []string) []byte {
	if len(args) != 1 {
		return Encode(errors.New("ERR wrong number of arguments for 'get' command"), false)
	}

	var key string = args[0]