Skip to content

Add HINCRBY, HINCRBYFLOAT and HSETNX hash commands#25

Merged
Rohit-Dnath merged 10 commits into
Rohit-Dnath:mainfrom
tchalikanti1705:add-hash-commands
Jul 8, 2026
Merged

Add HINCRBY, HINCRBYFLOAT and HSETNX hash commands#25
Rohit-Dnath merged 10 commits into
Rohit-Dnath:mainfrom
tchalikanti1705:add-hash-commands

Conversation

@tchalikanti1705

Copy link
Copy Markdown
Contributor

Summary

Adds the HINCRBY, HINCRBYFLOAT, and HSETNX hash commands so RAMen matches Redis for common hash counters and conditional field writes.

Related Issue

Closes #5

Changes

  • HSETNX <key> <field> <value> — sets a hash field only when it does not already exist and returns 1 or 0
  • HINCRBY <key> <field> <increment> — increments an integer hash field, treating missing fields as 0
  • HINCRBYFLOAT <key> <field> <increment> — increments a float hash field and rejects invalid, NaN, and infinite values
  • Added HSetNX, HIncrBy, and HIncrByFloat methods in internal/store/hash.go
  • Added command handlers and registrations in internal/server/cmd_hash.go and internal/server/commands.go
  • Added tests in internal/store/store_test.go and internal/server/server_test.go, and documented the commands in docs/commands.md

Checklist

  • [ x] I have read CONTRIBUTING.md
  • [ x] Tests pass (go test ./...)
  • [ x] Code is formatted (go fmt ./...)

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Redis-compatible hash counter and conditional write commands to RAMen, extending the existing hash feature set to support common counter/update patterns.

Changes:

  • Implemented HSETNX, HINCRBY, and HINCRBYFLOAT in the store layer (including overflow / NaN / Inf handling).
  • Registered new commands and added server-side handlers for the RESP API surface.
  • Added store + server integration tests and updated the command documentation.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
internal/store/string.go Introduces new shared error values used by hash increment logic.
internal/store/hash.go Implements HSetNX, HIncrBy, and HIncrByFloat in the storage layer.
internal/store/store_test.go Adds unit tests covering new hash semantics and edge cases (wrong type, overflow, NaN/Inf).
internal/server/cmd_hash.go Adds command handlers for HSETNX, HINCRBY, HINCRBYFLOAT.
internal/server/commands.go Registers the new hash commands.
internal/server/server_test.go Adds end-to-end server tests for new commands and error paths.
docs/commands.md Documents the new hash commands and provides examples.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread internal/store/hash.go
Comment on lines +131 to +136
// normalize negative zero so we return "0", not "-0", like Redis
if cur == 0 {
cur = 0
}
out := strconv.FormatFloat(cur, 'f', -1, 64)
h[field] = out
Comment thread internal/store/string.go
Comment on lines +17 to +24
// ErrIntegerOverflow is returned when an increment would overflow int64.
var ErrIntegerOverflow = errors.New("ERR increment or decrement would overflow")

// ErrNotFloat is returned when a value cannot be parsed as a finite float64.
var ErrNotFloat = errors.New("ERR value is not a valid float")

// ErrFloatOverflow is returned when a float increment would produce NaN or Infinity.
var ErrFloatOverflow = errors.New("ERR increment would produce NaN or Infinity")

@Rohit-Dnath Rohit-Dnath left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this @tchalikanti1705 , really solid work. 🙌

Pulled it down and ran everything locally: tests pass (including your 6 new ones), gofmt and go vet are clean, and it slots right into the existing HSet conventions. Snapshot persistence picks up the new fields for free too.

What stood out is how careful the edge cases are: overflow/underflow, NaN/Inf, negative-zero, WRONGTYPE, and asserting the field stays untouched when an op errors. That last one is the bit most people forget.

One tiny future-cleanup thought (not blocking): the get-or-create-hash block now repeats across the four write methods, so a small hashForWrite helper could tidy it up someday. Totally fine as-is since it matches the current style.

Approving and merging. Nice contribution! 🚀

@Rohit-Dnath Rohit-Dnath merged commit 8f2e2a0 into Rohit-Dnath:main Jul 8, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add HINCRBY / HINCRBYFLOAT / HSETNX hash commands

3 participants