Extbase:为并发访问实现锁定
Extbase: implement locking for concurrent access
在我的扩展中,我有一组由用户活动生成的操作。每个操作由几个步骤组成。
为了处理这些操作,我实施了一个调度程序任务(扩展名 "scheduler" 6.2.0)。现在的重点是:每个操作的步骤必须一个接一个地进行,不能并行进行。这意味着:在开始时,调度程序任务应该找到下一个 "free" 操作,锁定并处理它。
出于锁定目的,带操作的数据库 table 有一个整数列 "isLocked"。所以我想使用以下 SQL 语句来锁定操作:
$lockID = time();
'UPDATE operations SET isLocked = '.$lockID.' WHERE isLocked = 0 AND uid = '.$freeOperationFound->getUid().';
'
在这个 SQL 命令之后我想检查是否设置了锁定:
$repository->findOneByIsLocked($lockID);
如果锁定成功,操作步骤处理可以开始。
如果同时另一个调度程序任务实例锁定此操作,则上面的 SQL 语句不执行任何操作,因为条件:WHERE isLocked = 0
.
问题是:Extbase 忽略 SQL UPDATE 语句。
如果我只是通过存储库更新自由操作对象,另一个任务实例的锁可能会被覆盖。我需要某种 "conditional" 更新。
我想我明白了:$GLOBALS['TYPO3_DB']->exec_UPDATEquery
就是答案。
唯一剩下的问题是,如果这个方法也在 FLOW 中被描述,就像 $query->statement
的 Repository。
虽然来自 DatabaseConnection class 的 exec_UPDATEquery 函数确实可以完成工作,但这里是通过 extbase 的解决方案。如果您需要在锁定后使用 Operation 对象,这可能更有意义。
$persistenceManager = GeneralUtilities::makeInstance('TYPO3\CMS\extbase\Persistence\PersistenceManager');
$freeOperation = $repository->findOneByIsLocked(0);
$freeOperation->setIsLocked(time());
$repository->update($freeOperation);
$persistenceManager->persistAll();
$freeOperation->myOperation();
$freeOperation->myOtherOperation();
$freeOperation->setIsLocked(0);
$repository->update($freeOperation);
$persistenceManager->persistAll();
您需要手动坚持的原因是,您的任务不在 ActionController 操作的上下文中。即使您是,它也不会自动保留您的更改,直到操作结束。通过 extbase 执行此操作可能是更安全的选择,因为您可以确保实际执行与刚刚锁定的完全相同的操作。
在我的扩展中,我有一组由用户活动生成的操作。每个操作由几个步骤组成。
为了处理这些操作,我实施了一个调度程序任务(扩展名 "scheduler" 6.2.0)。现在的重点是:每个操作的步骤必须一个接一个地进行,不能并行进行。这意味着:在开始时,调度程序任务应该找到下一个 "free" 操作,锁定并处理它。
出于锁定目的,带操作的数据库 table 有一个整数列 "isLocked"。所以我想使用以下 SQL 语句来锁定操作:
$lockID = time();
'UPDATE operations SET isLocked = '.$lockID.' WHERE isLocked = 0 AND uid = '.$freeOperationFound->getUid().';
'
在这个 SQL 命令之后我想检查是否设置了锁定:
$repository->findOneByIsLocked($lockID);
如果锁定成功,操作步骤处理可以开始。
如果同时另一个调度程序任务实例锁定此操作,则上面的 SQL 语句不执行任何操作,因为条件:WHERE isLocked = 0
.
问题是:Extbase 忽略 SQL UPDATE 语句。
如果我只是通过存储库更新自由操作对象,另一个任务实例的锁可能会被覆盖。我需要某种 "conditional" 更新。
我想我明白了:$GLOBALS['TYPO3_DB']->exec_UPDATEquery
就是答案。
唯一剩下的问题是,如果这个方法也在 FLOW 中被描述,就像 $query->statement
的 Repository。
虽然来自 DatabaseConnection class 的 exec_UPDATEquery 函数确实可以完成工作,但这里是通过 extbase 的解决方案。如果您需要在锁定后使用 Operation 对象,这可能更有意义。
$persistenceManager = GeneralUtilities::makeInstance('TYPO3\CMS\extbase\Persistence\PersistenceManager');
$freeOperation = $repository->findOneByIsLocked(0);
$freeOperation->setIsLocked(time());
$repository->update($freeOperation);
$persistenceManager->persistAll();
$freeOperation->myOperation();
$freeOperation->myOtherOperation();
$freeOperation->setIsLocked(0);
$repository->update($freeOperation);
$persistenceManager->persistAll();
您需要手动坚持的原因是,您的任务不在 ActionController 操作的上下文中。即使您是,它也不会自动保留您的更改,直到操作结束。通过 extbase 执行此操作可能是更安全的选择,因为您可以确保实际执行与刚刚锁定的完全相同的操作。