Skip to content
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

support etag in redis state provider #579

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

RemindD
Copy link
Contributor

@RemindD RemindD commented Dec 9, 2024

No description provided.

@@ -147,9 +177,17 @@ func (r *RedisStateProvider) Upsert(ctx context.Context, entry states.UpsertRequ
if err != nil {
return entry.Value.ID, err
}
firstWrite := 0
if entry.Options.Concurrency == states.FirstWrite {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean "first write win"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. If two writes with the same ETag coming in, the first write will win and bump etag while the second write fails.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hi @RemindD , I think this PR will be a little overlapped with #568, let's finalize #568 at first then go through this PR.

if etag == "" {
etag = "0"
}
err = r.Client.Do(r.Ctx, "EVAL", setDefaultQuery, 1, key, etag, string(body), 1).Err()
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the last parameter be firstWrite?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I really want to remove UpdateStatusOnly option because the caller should get the previous state first, apply the update and then upsert with etag.
Here the upsert operation is based on the previous get result so the firstWrite should always be 1.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer we still keep UpdateStatusOnly since like K8S state provider, status are sub resources. But seems we should not always default to useFirstWriteWins or lastWriteWins when updating status. As state provider, it is better we align client's input. And for all clients, they need to handle get state at first before composing new state.

if not etag or type(etag)=="table" or etag == "" or etag == ARGV[1] or (not fwr and ARGV[1] == "0") then
redis.call("HSET", KEYS[1], "values", ARGV[2]);
if ARGV[3] == "1" then
redis.call("HSET", KEYS[1], "first-write", 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

It reads like the first-write field is actually used to distinguish between first write request from other requests? What if two clients sending the request at the same time?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This logic is from the Dapr project and I think this is to guarantee all the further operations should use proper etag if any one is firstwrite. If you have different expectation, I can change it based on our need.

redis.call("DEL", KEYS[1]);
end;
local fwr = redis.pcall("HGET", KEYS[1], "first-write");
if not etag or type(etag)=="table" or etag == "" or etag == ARGV[1] or (not fwr and ARGV[1] == "0") then
Copy link
Contributor

Choose a reason for hiding this comment

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

What does type(etag)=="table" mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This condition is copied from dapr repo. It means the etag is not a proper column name, likely for error case handling.

@@ -222,11 +267,11 @@ func (r *RedisStateProvider) List(ctx context.Context, request states.ListReques
continue
}
parts := strings.Split(key, separator)
if len(parts) != 3 {
if len(parts) != 4 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Give an example of new key in comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added

@RemindD RemindD force-pushed the users/xingdong/redisetag branch from 58ee6af to 31f906a Compare December 31, 2024 08:52
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.

3 participants