Skip to content

feat: func isEmptyValue support time.Time #3273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 28, 2025
Merged

Conversation

gh73962
Copy link
Contributor

@gh73962 gh73962 commented Feb 10, 2025

This PR is based on the solution discussed in the #3208 issue.

@ndyakov
Copy link
Member

ndyakov commented Feb 10, 2025

@gh73962 Thank you for the contribution. The test that you have added would have passed with or without the addition you did. Can we check what will be read so we verify the data. Maybe a raw read would work, since if we unmarshal the response to the object it would be the same as before, won't it?

@gh73962
Copy link
Contributor Author

gh73962 commented Feb 11, 2025

@gh73962 Thank you for the contribution. The test that you have added would have passed with or without the addition you did. Can we check what will be read so we verify the data. Maybe a raw read would work, since if we unmarshal the response to the object it would be the same as before, won't it?

Of course, I don't have the capability to perform this kind of test on my side. Changes like this should have comprehensive tests to ensure code quality.

@ndyakov ndyakov self-requested a review February 21, 2025 12:09
@ndyakov ndyakov changed the title fix: func isEmptyValue support time.Time feat: func isEmptyValue support time.Time Feb 21, 2025
@ndyakov
Copy link
Member

ndyakov commented Feb 26, 2025

@gh73962 would you like me to help you add those tests? The CI will run a redis server, you should be able to execute code agains it in the tests (you can check the existing tests for Set and Get). Let me know if I can help you somehow.

@gh73962
Copy link
Contributor Author

gh73962 commented Feb 26, 2025

@gh73962 would you like me to help you add those tests? The CI will run a redis server, you should be able to execute code agains it in the tests (you can check the existing tests for Set and Get). Let me know if I can help you somehow.

Of course

@ndyakov
Copy link
Member

ndyakov commented Feb 27, 2025

@gh73962 any concrete questions on how to write tests? will you be able to do this on your own?

@gh73962
Copy link
Contributor Author

gh73962 commented Feb 28, 2025

In my first commit of the commands_test.go file, the added test covers a scenario that our team frequently encounters.I need you guide, What additional test cases should I include?

@ndyakov ndyakov requested a review from Copilot March 7, 2025 15:09
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

PR Overview

This PR adds support in the isEmptyValue function to correctly handle time.Time values by leveraging Go’s reflect.IsZero.

  • Updated commands.go to use v.IsZero() for reflect.Struct to check for zero values.
  • Extended commands_test.go with a new test struct (set2) including a time.Time field to validate the new functionality.

Reviewed Changes

File Description
commands.go Added reflect.Struct case using v.IsZero() for isEmptyValue.
commands_test.go Added a test struct with a time.Time field to exercise the new functionality.

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

Comments suppressed due to low confidence (2)

commands_test.go:2581

  • Consider adding a test case where the time.Time value is set to a non-zero value to confirm that non-empty time values are handled correctly.
Set5 time.Time     `redis:"set5,omitempty"`

commands.go:156

  • Review whether applying v.IsZero() to all structs might have unintended consequences for non-time.Time types. If this branch is intended only for time.Time support, consider verifying or isolating behavior for other struct types.
case reflect.Struct:

@ndyakov
Copy link
Member

ndyakov commented Mar 24, 2025

@gh73962 lets add tests for the following scenarios:

  • Add a test with custom struct in the hash that wants to hold a zero value (for example type RequestsSetting struct { Limit int } and the limit set to zero. Check if the struct is parsed correctly when the data is requested from redis.
  • Add a test which validates that the data that was received from redis is what was written to redis. For example add a test where you set the time.Time value and validate that the same is parsed later when reading the data.

@gh73962
Copy link
Contributor Author

gh73962 commented Mar 24, 2025

@gh73962 lets add tests for the following scenarios:

* Add a test with custom struct in the hash that wants to hold a zero value (for example `type RequestsSetting struct { Limit int }` and the limit set to zero. Check if the struct is parsed correctly when the data is requested from redis.

* Add a test which validates that the data that was received from redis is what was written to redis. For example add a test where you set the `time.Time` value and validate that the same is parsed later when reading the data.

add to commands_test.go It("should HSet", func() ?

@ndyakov
Copy link
Member

ndyakov commented Mar 24, 2025

@gh73962 yes.

@ndyakov
Copy link
Member

ndyakov commented Apr 2, 2025

@gh73962 can we try with a child struct? Would you like me to write the tests or you would do it?

Copy link
Member

@ndyakov ndyakov left a comment

Choose a reason for hiding this comment

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

I don't find the testing sufficient. Please check the discussion so far.

@gh73962
Copy link
Contributor Author

gh73962 commented Apr 2, 2025

@ndyakov I was sick a few days ago, and I'll start improving these tasks tomorrow.

@gh73962
Copy link
Contributor Author

gh73962 commented Apr 2, 2025

@gh73962 can we try with a child struct? Would you like me to write the tests or you would do it?

I can test it out and check the impact on the child struct. Should I write the tests, or will you?

@gh73962
Copy link
Contributor Author

gh73962 commented Apr 3, 2025

@ndyakov pls review and hset.Scan not support struct
图片

@gh73962
Copy link
Contributor Author

gh73962 commented Apr 4, 2025

@ndyakov pls review and hset.Scan not support struct 图片

Additional note: hGetAll.Scan does not support parsing into nested structs, not that Scan doesn't support structs in general. The current issue is that hset supports implementing the BinaryMarshaler interface, while Scan fails to support nested BinaryUnmarshaler, creating an asymmetry in functionality. I believe redisv9's hset and scan are very developer-friendly, which is why my team migrated from v6 to v9. I hope go-redis can align the capabilities of hset and scan in the future. Thank you very much.
@ndyakov

@gh73962
Copy link
Contributor Author

gh73962 commented Apr 23, 2025

@ndyakov hi,pls check this PR

@ndyakov
Copy link
Member

ndyakov commented Apr 24, 2025

@gh73962 feel free to add the additional check for time.Time and write two tests - one for time.Time and one for a custom struct that holds an integer (you can test with an empty int and with a value that is different than 0).

@gh73962 gh73962 force-pushed the master branch 2 times, most recently from ad2dc44 to ffce047 Compare April 28, 2025 08:25
@gh73962
Copy link
Contributor Author

gh73962 commented Apr 28, 2025

@ndyakov pls review

@ndyakov ndyakov requested review from Copilot and ndyakov April 28, 2025 20:43
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR implements support for time.Time in the isEmptyValue function and updates related tests to verify correct behavior. Key changes include:

  • Adding a new case for time.Time in isEmptyValue.
  • Introducing a test struct (setOmitEmpty) that verifies omitting empty fields, including time.Time values.
  • Refactoring numberStruct methods by renaming receiver variables and replacing a duplicate UnmarshalBinary with a new ScanRedis method.

Reviewed Changes

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

File Description
commands_test.go Added tests for new behavior with time.Time and updated numberStruct methods
commands.go Extended isEmptyValue to properly handle time.Time structures
Comments suppressed due to low confidence (1)

commands_test.go:7678

  • [nitpick] Consider revisiting the naming of ScanRedis to keep it consistent with MarshalBinary if their functionalities are analogous, or add a comment to clarify the intended difference in behavior between ScanRedis and UnmarshalBinary.
func (n *numberStruct) ScanRedis(str string) error {

Copy link
Member

@ndyakov ndyakov left a comment

Choose a reason for hiding this comment

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

Added one additional case, overall looks good.

@ndyakov ndyakov merged commit 4bd5d41 into redis:master Apr 28, 2025
16 checks passed
ndyakov added a commit that referenced this pull request Apr 30, 2025
* fix:func isEmptyValue support time.Time

* fix: Improve HSet unit tests

* feat: Improve HSet unit tests

* fix: isEmptyValue Struct only support time.Time

* test(hset): add empty custom struct test

---------

Co-authored-by: Guo Hui <[email protected]>
Co-authored-by: Nedyalko Dyakov <[email protected]>
project-mirrors-bot-tu bot pushed a commit to project-mirrors/forgejo that referenced this pull request May 1, 2025
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/redis/go-redis/v9](https://github.com/redis/go-redis) | require | minor | `v9.7.3` -> `v9.8.0` |

---

### Release Notes

<details>
<summary>redis/go-redis (github.com/redis/go-redis/v9)</summary>

### [`v9.8.0`](https://github.com/redis/go-redis/releases/tag/v9.8.0)

[Compare Source](redis/go-redis@v9.7.3...v9.8.0)

### 9.8.0 (2025-04-30)

#### 🚀 Highlights

-   **Redis 8 Support**: Full compatibility with Redis 8.0, including testing and CI integration
-   **Enhanced Hash Operations**: Added support for new hash commands (`HGETDEL`, `HGETEX`, `HSETEX`) and `HSTRLEN` command
-   **Search Improvements**: Enabled Search DIALECT 2 by default and added `CountOnly` argument for `FT.Search`

#### ✨ New Features

-   Added support for new hash commands: `HGETDEL`, `HGETEX`, `HSETEX` ([#&#8203;3305](redis/go-redis#3305))
-   Added `HSTRLEN` command for hash operations ([#&#8203;2843](redis/go-redis#2843))
-   Added `Do` method for raw query by single connection from `pool.Conn()` ([#&#8203;3182](redis/go-redis#3182))
-   Prevent false-positive marshaling by treating zero time.Time as empty in isEmptyValue ([#&#8203;3273](redis/go-redis#3273))
-   Added FailoverClusterClient support for Universal client ([#&#8203;2794](redis/go-redis#2794))
-   Added support for cluster mode with `IsClusterMode` config parameter ([#&#8203;3255](redis/go-redis#3255))
-   Added client name support in `HELLO` RESP handshake ([#&#8203;3294](redis/go-redis#3294))
-   **Enabled Search DIALECT 2 by default** ([#&#8203;3213](redis/go-redis#3213))
-   Added read-only option for failover configurations ([#&#8203;3281](redis/go-redis#3281))
-   Added `CountOnly` argument for `FT.Search` to use `LIMIT 0 0` ([#&#8203;3338](redis/go-redis#3338))
-   Added `DB` option support in `NewFailoverClusterClient` ([#&#8203;3342](redis/go-redis#3342))
-   Added `nil` check for the options when creating a client ([#&#8203;3363](redis/go-redis#3363))

#### 🐛 Bug Fixes

-   Fixed `PubSub` concurrency safety issues ([#&#8203;3360](redis/go-redis#3360))
-   Fixed panic caused when argument is `nil` ([#&#8203;3353](redis/go-redis#3353))
-   Improved error handling when fetching master node from sentinels ([#&#8203;3349](redis/go-redis#3349))
-   Fixed connection pool timeout issues and increased retries ([#&#8203;3298](redis/go-redis#3298))
-   Fixed context cancellation error leading to connection spikes on Primary instances ([#&#8203;3190](redis/go-redis#3190))
-   Fixed RedisCluster client to consider `MASTERDOWN` a retriable error ([#&#8203;3164](redis/go-redis#3164))
-   Fixed tracing to show complete commands instead of truncated versions ([#&#8203;3290](redis/go-redis#3290))
-   Fixed OpenTelemetry instrumentation to prevent multiple span reporting ([#&#8203;3168](redis/go-redis#3168))
-   Fixed `FT.Search` Limit argument and added `CountOnly` argument for limit 0 0 ([#&#8203;3338](redis/go-redis#3338))
-   Fixed missing command in interface ([#&#8203;3344](redis/go-redis#3344))
-   Fixed slot calculation for `COUNTKEYSINSLOT` command ([#&#8203;3327](redis/go-redis#3327))
-   Updated PubSub implementation with correct context ([#&#8203;3329](redis/go-redis#3329))

#### 📚 Documentation

-   Added hash search examples ([#&#8203;3357](redis/go-redis#3357))
-   Fixed documentation comments ([#&#8203;3351](redis/go-redis#3351))
-   Added `CountOnly` search example ([#&#8203;3345](redis/go-redis#3345))
-   Added examples for list commands: `LLEN`, `LPOP`, `LPUSH`, `LRANGE`, `RPOP`, `RPUSH` ([#&#8203;3234](redis/go-redis#3234))
-   Added `SADD` and `SMEMBERS` command examples ([#&#8203;3242](redis/go-redis#3242))
-   Updated `README.md` to use Redis Discord guild ([#&#8203;3331](redis/go-redis#3331))
-   Updated `HExpire` command documentation ([#&#8203;3355](redis/go-redis#3355))
-   Featured OpenTelemetry instrumentation more prominently ([#&#8203;3316](redis/go-redis#3316))
-   Updated `README.md` with additional information ([#&#8203;310ce55](redis/go-redis@310ce55))

#### ⚡ Performance and Reliability

-   Bound connection pool background dials to configured dial timeout ([#&#8203;3089](redis/go-redis#3089))
-   Ensured context isn't exhausted via concurrent query ([#&#8203;3334](redis/go-redis#3334))

#### 🔧 Dependencies and Infrastructure

-   Updated testing image to Redis 8.0-RC2 ([#&#8203;3361](redis/go-redis#3361))
-   Enabled CI for Redis CE 8.0 ([#&#8203;3274](redis/go-redis#3274))
-   Updated various dependencies:
    -   Bumped golangci/golangci-lint-action from 6.5.0 to 7.0.0 ([#&#8203;3354](redis/go-redis#3354))
    -   Bumped rojopolis/spellcheck-github-actions ([#&#8203;3336](redis/go-redis#3336))
    -   Bumped golang.org/x/net in example/otel ([#&#8203;3308](redis/go-redis#3308))
-   Migrated golangci-lint configuration to v2 format ([#&#8203;3354](redis/go-redis#3354))

#### ⚠️ Breaking Changes

-   **Enabled Search DIALECT 2 by default** ([#&#8203;3213](redis/go-redis#3213))
-   Dropped RedisGears (Triggers and Functions) support ([#&#8203;3321](redis/go-redis#3321))
-   Dropped FT.PROFILE command that was never enabled ([#&#8203;3323](redis/go-redis#3323))

#### 🔒 Security

-   Fixed network error handling on SETINFO (CVE-2025-29923) ([#&#8203;3295](redis/go-redis#3295))

#### 🧪 Testing

-   Added integration tests for Redis 8 behavior changes in Redis Search ([#&#8203;3337](redis/go-redis#3337))
-   Added vector types INT8 and UINT8 tests ([#&#8203;3299](redis/go-redis#3299))
-   Added test codes for search_commands.go ([#&#8203;3285](redis/go-redis#3285))
-   Fixed example test sorting ([#&#8203;3292](redis/go-redis#3292))

#### 👥 Contributors

We would like to thank all the contributors who made this release possible:

[@&#8203;alexander-menshchikov](https://github.com/alexander-menshchikov), [@&#8203;EXPEbdodla](https://github.com/EXPEbdodla), [@&#8203;afti](https://github.com/afti), [@&#8203;dmaier-redislabs](https://github.com/dmaier-redislabs), [@&#8203;four_leaf_clover](https://github.com/four_leaf_clover), [@&#8203;alohaglenn](https://github.com/alohaglenn), [@&#8203;gh73962](https://github.com/gh73962), [@&#8203;justinmir](https://github.com/justinmir), [@&#8203;LINKIWI](https://github.com/LINKIWI), [@&#8203;liushuangbill](https://github.com/liushuangbill), [@&#8203;golang88](https://github.com/golang88), [@&#8203;gnpaone](https://github.com/gnpaone), [@&#8203;ndyakov](https://github.com/ndyakov), [@&#8203;nikolaydubina](https://github.com/nikolaydubina), [@&#8203;oleglacto](https://github.com/oleglacto), [@&#8203;andy-stark-redis](https://github.com/andy-stark-redis), [@&#8203;rodneyosodo](https://github.com/rodneyosodo), [@&#8203;dependabot](https://github.com/dependabot), [@&#8203;rfyiamcool](https://github.com/rfyiamcool), [@&#8203;frankxjkuang](https://github.com/frankxjkuang), [@&#8203;fukua95](https://github.com/fukua95), [@&#8203;soleymani-milad](https://github.com/soleymani-milad), [@&#8203;ofekshenawa](https://github.com/ofekshenawa), [@&#8203;khasanovbi](https://github.com/khasanovbi)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNjEuNCIsInVwZGF0ZWRJblZlciI6IjM5LjI2MS40IiwidGFyZ2V0QnJhbmNoIjoiZm9yZ2VqbyIsImxhYmVscyI6WyJkZXBlbmRlbmN5LXVwZ3JhZGUiLCJ0ZXN0L25vdC1uZWVkZWQiXX0=-->

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7739
Reviewed-by: Earl Warren <[email protected]>
Co-authored-by: Renovate Bot <[email protected]>
Co-committed-by: Renovate Bot <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants