Address remaining review items: Synapse caching, cycle detection, cache/ratelimit/kanban
Security / PHP Security (semgrep) (push) Successful in 1m45s
Lint / Deploy (push) Successful in 3s
Lint / Notify on failure (push) Has been skipped
Lint / PHP (phpcs PSR-12) (push) Successful in 21s
Lint / JS (eslint) (push) Successful in 9s
Lint / PHP requirements (version + extensions) (push) Successful in 26s
Security / PHP Security (semgrep) (push) Successful in 1m45s
Lint / Deploy (push) Successful in 3s
Lint / Notify on failure (push) Has been skipped
Lint / PHP (phpcs PSR-12) (push) Successful in 21s
Lint / JS (eslint) (push) Successful in 9s
Lint / PHP requirements (version + extensions) (push) Successful in 26s
- SynapseHelper: memoize username->Matrix-ID lookups per-request (incl. negative
results) and add an overall time budget to resolveUsernames() plus a 2s connect
timeout, so notifying N watchers with a slow/unreachable Synapse can't stall the
request for N x 5s. (Chosen over async/queue per maintainer.)
- DependencyModel: fix cycle detection treating 'blocks' and 'blocked_by' as the
same edge direction. They are inverse relationships (single row each, no mirror
row), so the traversal now walks a unified precedence graph (blocks: ticket->
depends_on; blocked_by: depends_on->ticket) and wouldCreateCycle normalizes the
new edge's direction. Prevents both false-positive and missed cycles.
- CacheHelper: anchor prefix-delete to exact key boundaries (bare prefix or
prefix + '_' + md5) so delete('workflow') can't wipe a 'workflow_rules' cache.
- RateLimitMiddleware: hold an exclusive flock across the per-IP counter's
read-modify-write so concurrent requests can't both read N and write N+1
(undercounting past the limit). Fails open if the file can't be locked.
- dashboard.js: kanban status update now uses lt.api.post (per no-raw-fetch
convention) and reverts the card AND the optimistic column counts on failure
(the old raw-fetch catch left the card moved without reverting).
- BulkOperationsModel: document that bulk_status/bulk_close intentionally bypass
workflow transition validation (admin override, by design).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+13
-6
@@ -125,16 +125,23 @@ class CacheHelper
|
||||
return !file_exists($filePath) || @unlink($filePath);
|
||||
}
|
||||
|
||||
// Delete all files with this prefix
|
||||
$pattern = self::getCacheDir() . '/' . preg_replace('/[^a-zA-Z0-9_]/', '_', $prefix) . '*.json';
|
||||
$files = glob($pattern);
|
||||
// Delete all entries for this prefix. A key is either the bare prefix or
|
||||
// prefix + '_' + md5(identifier) (32 hex chars, see makeKey). Match exactly
|
||||
// that so a prefix can't clobber a different prefix that merely shares a
|
||||
// leading substring — e.g. delete('workflow') must not wipe 'workflow_rules'.
|
||||
$safePrefix = preg_replace('/[^a-zA-Z0-9_]/', '_', $prefix);
|
||||
$keyRegex = '/^' . preg_quote($safePrefix, '/') . '(_[0-9a-f]{32})?$/';
|
||||
|
||||
$files = glob(self::getCacheDir() . '/' . $safePrefix . '*.json') ?: [];
|
||||
foreach ($files as $file) {
|
||||
@unlink($file);
|
||||
if (preg_match($keyRegex, basename($file, '.json'))) {
|
||||
@unlink($file);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear memory cache entries with this prefix
|
||||
// Clear matching memory cache entries
|
||||
foreach (array_keys(self::$memoryCache) as $key) {
|
||||
if (strpos($key, $prefix) === 0) {
|
||||
if (preg_match($keyRegex, $key)) {
|
||||
unset(self::$memoryCache[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user