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

clears commandTimeout timer as each respective command gets fulfilled #1336

Merged
merged 9 commits into from
Apr 24, 2021

Conversation

JosePedroDiasSky
Copy link
Contributor

@JosePedroDiasSky JosePedroDiasSky commented Apr 14, 2021

Currently, using the commandTimeout option is creating one timer per command and they're not being cleared as each command gets fulfilled. This PR does that.

@JosePedroDiasSky JosePedroDiasSky changed the title cleans commandTimeout timer as respective commands get fulfilled clears commandTimeout timer as respective each respective command gets fulfilled Apr 14, 2021
@JosePedroDiasSky JosePedroDiasSky changed the title clears commandTimeout timer as respective each respective command gets fulfilled clears commandTimeout timer as each respective command gets fulfilled Apr 14, 2021
@luin
Copy link
Collaborator

luin commented Apr 14, 2021

@mjomble Can you take a look?

lib/command.ts Outdated
@@ -156,6 +156,7 @@ export default class Command implements ICommand {
public isCustomCommand = false;
public inTransaction = false;
public pipelineIndex?: number;
private _commandTimeoutTimer?: ReturnType<typeof setTimeout>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Should be able to just use NodeJS.Timeout as the type

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Looks ok, but I'm not sure if it's necessary.
Are the timers causing actual measurable performance problems or other issues without this change?

If we start clearing them just in case, we should also consider the cost of increased code complexity (maintenance overhead, wider surface area for possible future bugs etc).
Sometimes an optimization saves a few microseconds of CPU time, but can cost hours of developer time at some point in the future.
Might not be the case here, but just something to consider 🙂

If you have a lingering timeout per command and you're doing several commands I'd say it's relevant and the additional complexity for this single operation is marginal, but it's up to you.

Regarding the type change, I can do as your suggested if you feel it's a better fit than using return type. I had tried Timeout without the namespace and number as well and ended up here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated the type as suggested.

@mjomble
Copy link
Contributor

mjomble commented Apr 14, 2021

Looks ok, but I'm not sure if it's necessary.
Are the timers causing actual measurable performance problems or other issues without this change?

If we start clearing them just in case, we should also consider the cost of increased code complexity (maintenance overhead, wider surface area for possible future bugs etc).
Sometimes an optimization saves a few microseconds of CPU time, but can cost hours of developer time at some point in the future.
Might not be the case here, but just something to consider 🙂

@mjomble
Copy link
Contributor

mjomble commented Apr 19, 2021

In case more comments are expected from me before merging this:

I haven't done any actual performance testing (either with or without this change), but it looks ok to merge 🙂

When client is not ready, Redis#sendCommand() will move
commands to the offline queue, and once ready, all commands
in the offline queue will be sent with Redis#sendCommand()
again. So we should check whether the timer has been set.
@luin
Copy link
Collaborator

luin commented Apr 24, 2021

@mjomble I just added another commit to fix leaking timers caused by commands being sent with Redis#sendCommand() twice (because once client is ready, commands in the offline queue will be sent with Redis#sendCommand() again). Can you review again and squash this (you are a collaborator so should have permission to do this)?

I think comparing to performance, it makes more sense to merge this commit for functionality reasons as pending timers prevent the process from exiting. For example, before this PR the following code won't exit:

const Redis = require("ioredis");
const redis = new Redis({ commandtimeout: 100000000 });

redis.set("foo", "bar").finally(() => {
  redis.disconnect();
  console.log("should exit now");
});

BTW We should always use squash instead of merge, the commit message for this PR should have a prefix of fix: . Refer to https://github.com/luin/ioredis/blob/master/.github/CONTRIBUTING.md for details. Thanks!

expect(clock.countTimers()).to.eql(0);
clock.restore();
redis.disconnect();
await new Promise((resolve) => server.disconnect(() => resolve(null)));
Copy link
Contributor

Choose a reason for hiding this comment

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

Now that #1328 is merged, you can use await server.disconnectPromise() here

@mjomble
Copy link
Contributor

mjomble commented Apr 24, 2021

LGTM


I think comparing to performance, it makes more sense to merge this commit for functionality reasons as pending timers prevent the process from exiting

Good point, I hadn't though of that.


Can you review again and squash this (you are a collaborator so should have permission to do this)?

I'm not sure if I should accept the collaborator invitation. Most of my changes were related to a project I'm working on, which is almost complete, so I probably won't be able to contribute much in the future 🙁

@luin
Copy link
Collaborator

luin commented Apr 24, 2021

Most of my changes were related to a project I'm working on, which is almost complete.

Oh, gotcha. Congratulations on your project completion! 😄

@luin luin merged commit d65f8b2 into redis:master Apr 24, 2021
ioredis-robot pushed a commit that referenced this pull request Apr 24, 2021
## [4.27.1](v4.27.0...v4.27.1) (2021-04-24)

### Bug Fixes

* clears commandTimeout timer as each respective command gets fulfilled ([#1336](#1336)) ([d65f8b2](d65f8b2))
@ioredis-robot
Copy link
Collaborator

🎉 This PR is included in version 4.27.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

janus-dev87 added a commit to janus-dev87/ioredis-work that referenced this pull request Mar 1, 2024
## [4.27.1](redis/ioredis@v4.27.0...v4.27.1) (2021-04-24)

### Bug Fixes

* clears commandTimeout timer as each respective command gets fulfilled ([#1336](redis/ioredis#1336)) ([d65f8b2](redis/ioredis@d65f8b2))
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.

4 participants