Skip to content

Conversation

@flooey
Copy link
Contributor

@flooey flooey commented Feb 17, 2025

Fix a bug in the code that handles determining the timestamp for values in the cache that's used to implement removing the oldest key when the limit is reached. The bug is in parsing the time returned by Redis, making it produce incorrect results when the leading portion of the microseconds moves from 09 to 10. This tended to reveal itself as flakiness in the test_limit unit test, which we were seeing around 1 in 200 runs.

The TIME operation in Redis returns the time as an array of two strings, the first holding the number of seconds and the second holding the number of microseconds. Importantly, the second string has no leading zeroes. The Lua code parses this by concatenating these strings together separated by a decimal point and then parsing that as a number, which produces incorrectly ordered results when faced with values like ("1234567", "999") and ("1234567", "1000"), parsing them as 1234567.999000 and 1234567.100000, respectively, meaning the second value will be expunged from the cache first despite being inserted second.

Instead, parse each returned string as a number and then combine them numerically, which produces the correct number in this situation.

I can't easily produce a test for this, because to test this deterministically you have to control the timestamps Redis produces, and the current testing setup uses a standalone Redis process. We have a internal unit test that uses freezegun and an in-process Redis fake to test it, but I didn't think you would want that level of change to the testing configuration just to make the test for this very narrow change work.

@taylorhakes
Copy link
Owner

Thanks @flooey for the fix. Can you update the format from 1000000 to 1_000_000, so it's easier to read? If you can also add a short comment about why it's divided 1mil it would be really appreciate it. It will help people in the future.

If you make those 2 minor changes, I will merge. Thanks again!

Fix a bug in the code that handles determining the timestamp for
values in the cache that's used to implement removing the oldest key
when the limit is reached.  The bug is in parsing the time returned by
Redis, making it produce incorrect results when the leading portion of
the microseconds moves from 09 to 10.  This tended to reveal itself as
flakiness in the `test_limit` unit test, which we were seeing around 1
in 200 runs.

The `TIME` operation in Redis returns the time as an array of two
strings, the first holding the number of seconds and the second
holding the number of microseconds.  Importantly, the second string
has no leading zeroes.  The Lua code parses this by concatenating
these strings together separated by a decimal point and then parsing
that as a number, which produces incorrectly ordered results when
faced with values like `("1234567", "999")` and `("1234567", "1000")`,
parsing them as 1234567.999000 and 1234567.100000, respectively,
meaning the second value will be expunged from the cache first despite
being inserted second.

Instead, parse each returned string as a number and then combine them
numerically, which produces the correct number in this situation.

I can't easily produce a test for this, because to test this
deterministically you have to control the timestamps Redis produces,
and the current testing setup uses a standalone Redis process.  We
have a internal unit test that uses `freezegun` and an in-process
Redis fake to test it, but I didn't think you would want that level of
change to the testing configuration just to make the test for this
very narrow change work.
@flooey
Copy link
Contributor Author

flooey commented Feb 17, 2025

Thanks @flooey for the fix. Can you update the format from 1000000 to 1_000_000, so it's easier to read? If you can also add a short comment about why it's divided 1mil it would be really appreciate it. It will help people in the future.

Sure thing, I've added a comment. Unfortunately, the 1000000 is in Lua, where 1_000_000 isn't a valid integer format. I could change it to 1e6 if you think that would be clearer?

@flooey
Copy link
Contributor Author

flooey commented Mar 13, 2025

Just checking in on this.

@taylorhakes taylorhakes merged commit 0dbbc93 into taylorhakes:master Mar 25, 2025
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.

2 participants