-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[Semaphore] Add a semaphore store based on locks #59202
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
base: 8.1
Are you sure you want to change the base?
[Semaphore] Add a semaphore store based on locks #59202
Conversation
6921d4f to
38cb65b
Compare
1fef9d7 to
84e0607
Compare
|
@jderusse if you have some free time maybe you can have a relook at the changes we did since your last review as you are I think most familiar with semaphore component. |
|
@jderusse what I'm stuck of how we can make the framework bundle integration for this. |
| "require-dev": { | ||
| "predis/predis": "^1.1|^2.0" | ||
| "predis/predis": "^1.1|^2.0", | ||
| "symfony/lock": "^5.4 || ^6.0 || ^7.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we really want to allow those old versions here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can change to everything the core team wants. Currently it works on this versions and I started with the 5.4 as its still supported LTS until 2029.
|
I really like this proposal! Is @jderusse's feedback to #59202 (comment) the only blocker? |
|
Yes would be nice to get some feedback from @jderusse specially not sure how we can create the
And the new framework:
lock: '%env(LOCK_DSN)%'
semaphore: 'lock://'but doesn't work aslong as the factories are static methods. |
| for ($i = 0; $i < $limit; ++$i) { | ||
| $index = ($startPoint + $i) % $limit; | ||
|
|
||
| $lock = $this->lockFactory->createLock($lockName.'_'.$index, $ttlInSecond, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you disable the auto-release feature, you should wrap this function in a try/catch to release locks in case of an exception (ie. network error)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure about the whole try catch handling can you have a look at it if you find a more readable way maybe?
| private function releaseLocks(array $locks, Key $key): void | ||
| { | ||
| foreach ($locks as $lock) { | ||
| $lock->release(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wrap in a try/catch in case one release fails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
still throw an exception?
If yes which exception?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lock::release could throw a LockReleasingException
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean what should we do with the catched exceptions?
Throw the first appeared exception again after all locks released:
$exceptions = [];
foreach ($locks as $lock) {
try {
$lock->release();
} catch (LockReleasingException $e) {
$exceptions[] = $e;
}
if ([] !== $exceptions) {
throw new $exceptions[0]; // ??
}
// ...
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes proabably the first one (or if you want combine all exception in a new object, but I think it's overkill)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jderusse implemented but as in the previous comment not 100% sure how to make it better readable
| { | ||
| $locks = $this->getExistingLocks($key); | ||
|
|
||
| if (\count($locks) === $key->getWeight()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we use === or >= ? I know the createLock method stops when the counters match, and this code is enough.
But what if by "chance" we acquire MORE lock than necessary? ie. for whatever reason, the value in getWeight is dynamic.
IMHO, it doesn't hurt readability to use if (\count($locks) >= $key->getWeight()) (here and bellow,) but it makes the code stronger.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implemented
…aseLocks correctly on failing semphore acquired
2f035bc to
9e2fc0e
Compare
Co-Authored-By: [email protected]<Jérémy Derussé>
I really liked the idea of a semaphore component but not have the possibility to use it without Redis it did not get a lot a drive and usage in our projects and we workaround using Locks.
So this idea did come up to have a Semaphore store which can use the existing lock component for it.
@lyrixx @jderusse