Skip to content

Conversation

@amayer5125
Copy link
Contributor

@amayer5125 amayer5125 commented Mar 26, 2022

We store arguments on the queue as an array, but there is only ever one element in that array. I can't think of a reason to have an array with only one element in it.

Old Structure:

{"queue":"default","class":["App\\Job\\HelloJob","execute"],"args":[{"name":"World","number":1,"bool":true}]}

New Structure:

{"queue":"default","class":["App\\Job\\HelloJob","execute"],"data":{"name":"World","number":1,"bool":true}}
Copy link
Member

@markstory markstory left a comment

Choose a reason for hiding this comment

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

I mentioned zero-downtime deploys a few times, and I think that is actually more important than developer facing backwards compatibility is. Code can be gradually upgraded, or in some cases fixed as one pull request. The in-flight messages of an application with more than a single webserver and queue worker will cross paths as deploying to multiple hosts/pods is not an atomic process.

Without a zero-downtime solution to the queue message format, we will require users to choose between:

  1. Never upgrading
  2. Requiring scheduled downtime.
  3. Losing data

All three of these sound like unfair requests when we as maintainers can choose to ignore it, or make other compromises to make the desired progress.

With that said, I'm not against requiring 'pit-stop' releases to make that zero-downtime upgrade work. For example the next release (0.1.4) could introduce the new format (but not remove the old). Then in 0.1.5 we can remove the old format. We can document this in an upgrade guide for the plugin and keep a list of what the pit-stops are for people who are upgrading.

Comment on lines 123 to 126
return $this->parsedBody['args'][0];
return $this->parsedBody['args'];
}

return Hash::get($this->parsedBody['args'][0], $key, $default);
return Hash::get($this->parsedBody['args'], $key, $default);
Copy link
Member

Choose a reason for hiding this comment

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

If we move forward with this, we should be able to handle old and new messages. This is important as during a deploy you'll have application instances emitting the old message format, and messages being consumed on a new worker process. By handling the old format and the new format we can provide users with a zero-downtime upgrade.

I would likely recommend using a different key than args for the new format. Because there will be argument lists that contain positional arguments a simple count check won't work. This will also necessitate emitting the args key as well because of cross talk during deploys.

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 see what you are saying. I'm not quite sure I agree that we need to provide a zero-downtime option for this since the package is still in beta, but I will take a stab at writing some code to support both.

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 went with the key data. I added a check to see if args exists and will use that. If args does not exist in the payload data is used. I updated all variables to be $data when dealing with this to denote the change.

Copy link
Member

Choose a reason for hiding this comment

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

I see what you are saying. I'm not quite sure I agree that we need to provide a zero-downtime option for this since the package is still in beta, but I will take a stab at writing some code to support both.

Even though we're still in beta its good to think about the upgrade process, as if we can make it smooth and painless for folks who update frequently then they will continue to update.

'queue' => $queue,
'class' => $callable,
'args' => [$args],
'args' => $args,
Copy link
Member

Choose a reason for hiding this comment

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

I agree that this wrapping array is a bit redundant. However, I'm concerned that there isn't a safe way to remove this without having duplicate data in the messages for at least a few releases.

Because $args can also be a positional list and have only one value eg. QueueManager::push(WelcomeMailer::class, [1]);. This scenario being functional right now, means we cannot reuse args and have a zero-downtime upgrade process.

Comment on lines 122 to 127
// support old jobs that still have args
if (array_key_exists('args', $this->parsedBody)) {
$data = $this->parsedBody['args'][0];
} else {
$data = $this->parsedBody['data'];
}
Copy link
Member

Choose a reason for hiding this comment

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

What about new messages that are consumed by old workers? Wouldn't they still be missing their arguments?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is true. I guess for a short time we will need to double up the args and data in the payload until we remove args. I pushed an update.

args key is changed to data key to support backwards compatability
@markstory markstory merged commit 81d7bc9 into cakephp:master Mar 28, 2022
@markstory
Copy link
Member

Thank you 👍

@amayer5125 amayer5125 deleted the flatten-args branch March 28, 2022 15:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants