Let's make the lock API more OO and more similar to the way database transactions are handled, like this:
The return value from lock()->acquire() should be an object with $lock->renew() and $lock->release() methods. If a lock object goes out of scope, it is automatically released.

This eliminates the need for the shutdown function and the lock()->releaseAll() method called from the shutdown function.

Comments

Status: Needs review » Needs work

The last submitted patch, lock-object-1.patch, failed testing.

olli’s picture

Missing Lock.php?

c960657’s picture

Status: Needs work » Needs review
StatusFileSize
new31.73 KB

Sorry, this patch includes Lock.php.

Status: Needs review » Needs work

The last submitted patch, lock-object-2.patch, failed testing.

c960657’s picture

Status: Needs work » Needs review
StatusFileSize
new33.49 KB

Status: Needs review » Needs work

The last submitted patch, lock-object-3.patch, failed testing.

c960657’s picture

Status: Needs work » Needs review
StatusFileSize
new33.39 KB

Status: Needs review » Needs work

The last submitted patch, lock-object-4.patch, failed testing.

c960657’s picture

Status: Needs work » Needs review
StatusFileSize
new34.3 KB
c960657’s picture

Issue tags: +API change, +API consistency

Bonus feature:
The code for acquiring and renewing locks is now split into two different methods. Today they are completely separate code paths but wrapped in the same function.

Positive side-effects that makes the Lock system more powerful without sacrificing simplicity or DX:

  1. Locks acquired by another process, that has terminated with a fatal error, can now be released, assuming the lock ID is known (releasing without knowing the ID is the subject of #1266568: Allow releasing a lock acquired by another process).
  2. Locks can be acquired in one request and released in another request, e.g. when used from the Batch API.
sun’s picture

1) I really like the architectural idea of Lock objects.

2) We cannot and must not rely on __destruct(). This is why: #843114: DatabaseConnection::__construct() and DatabaseConnection_mysql::__construct() leaks $this (Too many connections) — Tests are affected, too.

c960657’s picture

I don't understand your concern. #843114 was about destructors not being called due to circular references. This is not the case here, at least not unless the lock objects are stored in some static variable or similar so that garbage collection does not occur. I assume that even in the case of circular references, the destructor is eventually called at the end of the request?

On the other hand, I think it would be a good idea to make it preferred convention in core to always call $lock->release() method explicitly. This would make it more transparent what is going on.

Crell’s picture

The use of destruct() here is effectively the same as the way we use transaction objects in the database API. Those commit-on-destruct, and since they're local scope they'll die at the end of the function and release then. There's no end-of-request shutdown ordering issues to deal with. I'm not aware of any issues with our transaction code right now, so this should be fine, too.

pounard’s picture

Status: Needs review » Needs work

Note that this issue is a split of #1225404: Modernize lock acquisition to RAII.

I would rename autoRelease() to setAutoRelease() to make the method name more consistent.

Your patch causes a consistency problem, the backend should keep the release() low level method without the LockObject object in its signature, we should probably leave the backend as it was. The backend can be used without the lock object and should be kept as such.

The Lock class is an helper that should not be change the backend interface: the simpler the backend stays, the easier it is to implement, plus, many backends in contrib can be ported just by renaming methods today, by making it dependent on the Lock class, we loose easy porting of existing code. The Lock class doesn't bring anything valuable for the backend itself so it should exist in an upper code layer and leave the backend as it exists today.

To solve that a factory injected into the DIC should be used instead, that would handle the Lock instances.

c960657’s picture

I would rename autoRelease() to setAutoRelease() to make the method name more consistent.

Agreed.

by making it dependent on the Lock class, we loose easy porting of existing code.

Unless there is a common interface defined by PSR or similar, you would have to adjust the third-party code anyway. I don't think that it would not require a substantial larger effort to add support for the Lock class. It does not impose a functional requirement, just a way to wrap input and output arguments.

I can see how it would be possible to decouple the backend from the Lock objects, either by some factory method, or e.g. by reintroducing lock_acquire(), but I don't really see the benefit.

we should probably leave the backend as it was

One fundamental difference introduced by the patch is that with the patch you are required to specify the lock ID in order to renew or release a lock. This has the benefit that you don't release somebody else's lock by mistake, and it gives some possibilities with respect to cross-request locks. But of course this may be implemented without passing the Lock class around but simply the lock ID.

c960657’s picture

For the record, I am not convinced that cross-request locks is something we should support. But being able to unlock a stale lock from a separate request is important, I think.

pounard’s picture

One fundamental difference introduced by the patch is that with the patch you are required to specify the lock ID in order to renew or release a lock. This has the benefit that you don't release somebody else's lock by mistake, and it gives some possibilities with respect to cross-request locks. But of course this may be implemented without passing the Lock class around but simply the lock ID.

In actual core (both 7 and 8), as in my previous patch in the other issue, you cannot delete another thread lock thanks to the lock_id condition on all delete queries. The lock id is hidden from the public API just for this reason. I don't see where you patch change or fix anything of that.

I can see how it would be possible to decouple the backend from the Lock objects, either by some factory method, or e.g. by reintroducing lock_acquire(), but I don't really see the benefit.

Fair enough, we can skip the factory by making the backend manage directly the Lock instance, but having a factory arround would make the backend itself easier to implement (only atomic methods with primitive parameters) which decouples it from the upper layer and makes it being really simple and minimal, I think this would be a good idea to keep it this way.

c960657’s picture

In actual core (both 7 and 8), as in my previous patch in the other issue, you cannot delete another thread lock thanks to the lock_id condition on all delete queries. The lock id is hidden from the public API just for this reason. I don't see where you patch change or fix anything of that.

It does not change the situation with parallel requests. But within a request, you may run into a situation where the code attempts to acquired the same lock multiple times, especially with code that calls itself recursively. But okay, this may be an edge case.

pounard’s picture

It does not change the situation with parallel requests. But within a request, you may run into a situation where the code attempts to acquired the same lock multiple times, especially with code that calls itself recursively. But okay, this may be an edge case.

OK I understand your point here. In actual core, for example a recursive function, the lock is renew when acquired a second time. There is the release problem yes, but having such acquire() or release() calls in any kind of recursively called code would be design error. We should not encourage people to write wrong code.

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.9 was released on September 7 and is the final bugfix release for the Drupal 8.1.x series. Drupal 8.1.x will not receive any further development aside from security fixes. Drupal 8.2.0-rc1 is now available and sites should prepare to upgrade to 8.2.0.

Bug reports should be targeted against the 8.2.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.6 was released on February 1, 2017 and is the final full bugfix release for the Drupal 8.2.x series. Drupal 8.2.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.3.0 on April 5, 2017. (Drupal 8.3.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.3.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.6 was released on August 2, 2017 and is the final full bugfix release for the Drupal 8.3.x series. Drupal 8.3.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.4.0 on October 4, 2017. (Drupal 8.4.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.4.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.4 was released on January 3, 2018 and is the final full bugfix release for the Drupal 8.4.x series. Drupal 8.4.x will not receive any further development aside from critical and security fixes. Sites should prepare to update to 8.5.0 on March 7, 2018. (Drupal 8.5.0-alpha1 is available for testing.)

Bug reports should be targeted against the 8.5.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.8.x-dev

Drupal 8.6.x will not receive any further development aside from security fixes. Bug reports should be targeted against the 8.8.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.9.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.7 was released on June 3, 2020 and is the final full bugfix release for the Drupal 8.8.x series. Drupal 8.8.x will not receive any further development aside from security fixes. Sites should prepare to update to Drupal 8.9.0 or Drupal 9.0.0 for ongoing support.

Bug reports should be targeted against the 8.9.x-dev branch from now on, and new development or disruptive changes should be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 8.9.x-dev » 9.2.x-dev

Drupal 8 is end-of-life as of November 17, 2021. There will not be further changes made to Drupal 8. Bugfixes are now made to the 9.3.x and higher branches only. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.15 was released on June 1st, 2022 and is the final full bugfix release for the Drupal 9.3.x series. Drupal 9.3.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.4.x-dev branch from now on, and new development or disruptive changes should be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.9 was released on December 7, 2022 and is the final full bugfix release for the Drupal 9.4.x series. Drupal 9.4.x will not receive any further development aside from security fixes. Drupal 9 bug reports should be targeted for the 9.5.x-dev branch from now on, and new development or disruptive changes should be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

smustgrave’s picture

Issue summary: View changes
Status: Needs work » Postponed (maintainer needs more info)
Issue tags: +stale-issue-cleanup

Thank you for sharing your idea for improving Drupal.

We are working to decide if this proposal meets the Criteria for evaluating proposed changes. There hasn't been any discussion here for 8+ years which suggests that this has either been implemented or there is no community support. Your thoughts on this will allow a decision to be made.

Since we need more information to move forward with this issue, the status is now Postponed (maintainer needs more info). If we don't receive additional information to help with the issue, it may be closed after three months.

Thanks!

smustgrave’s picture

Status: Postponed (maintainer needs more info) » Closed (outdated)

3 months has past so closing out, but don't worry if still a valid task this can be re-opened by anyone.

Thanks!