diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index fdcf246..48ba975 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -25,7 +25,7 @@ jobs: fail-fast: true matrix: php: [7.3, 7.4, 8.0, 8.1] - stability: + stability: - prefer-stable name: PHP ${{ matrix.php }} - ${{ matrix.stability }} diff --git a/composer.json b/composer.json index 2bbfbbe..a62b133 100644 --- a/composer.json +++ b/composer.json @@ -2,6 +2,7 @@ "name": "always-open/laravel-process-stamps", "description": "Logs which process created or modified a record", "keywords": [ + "always open", "always-open", "laravel-process-stamps", "laravel", @@ -9,6 +10,26 @@ ], "homepage": "https://github.com/always-open/laravel-process-stamps", "license": "MIT", + "authors": [ + { + "name": "Tom Schlick", + "role": "Developer" + }, + { + "name": "Quentin Schmick", + "email": "qschmick@gmail.com", + "role": "Developer" + }, + { + "name": "Lucas Graciano", + "role": "Developer" + }, + { + "name": "Always Open", + "homepage": "https://github.com/always-open", + "role": "Organization" + } + ], "require": { "php": "^7.3|^8.0", "laravel/framework": "^8.0|^9.0" diff --git a/src/ProcessStamp.php b/src/ProcessStamp.php index 670450c..83463de 100644 --- a/src/ProcessStamp.php +++ b/src/ProcessStamp.php @@ -2,6 +2,7 @@ namespace AlwaysOpen\ProcessStamps; +use Exception; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -38,12 +39,12 @@ public function getTable() : string } /** - * @param array $process + * @param array $process * @param null|string $hash * * @return ProcessStamp * - * @throws ModelNotFoundException + * @throws ModelNotFoundException|Exception */ public static function firstOrCreateByProcess(array $process, ?string $hash = null) : self { @@ -55,31 +56,33 @@ public static function firstOrCreateByProcess(array $process, ?string $hash = nu $hash = static::makeProcessHash($process); } - $parent = null; + return retry(4, function() use ($hash, $process) { + $parent = null; - if (config('process-stamps.resolve_recursive') && ! empty($process['parent_name'])) { - $parent = static::firstOrCreateByProcess(static::getProcessName($process['type'], $process['parent_name'])); - } + if (config('process-stamps.resolve_recursive') && ! empty($process['parent_name'])) { + $parent = static::firstOrCreateByProcess(static::getProcessName($process['type'], $process['parent_name'])); + } + + $lock = Cache::lock('process-stamps-hash-create-' . $hash, 12); + $lock->block(3); - return retry(4, function() use ($hash, $process, $parent) { $stamp = static::firstWhere('hash', $hash); - /* - * If stamp does not exist in the database yet, go ahead and obtain a lock to create it. - * This specifically doesn't lock as the first step to avoid all calls obtaining a lock from the cache if - * the item already exists in the DB. - */ if (! $stamp) { - Cache::lock('process-stamps-hash-create-' . $hash, 10) - ->get(function () use (&$stamp, $hash, $process, $parent) { - $stamp = static::firstOrCreate(['hash' => $hash], [ - 'name' => trim($process['name']), - 'type' => $process['type'], - 'parent_id' => optional($parent)->getKey(), - ]); - }); + /* + * If stamp does not exist in the database yet, go ahead and obtain a lock to create it. + * This specifically doesn't lock as the first step to avoid all calls obtaining a lock from the cache + * if the item already exists in the DB. + */ + $stamp = static::firstOrCreate(['hash' => $hash], [ + 'name' => trim($process['name']), + 'type' => $process['type'], + 'parent_id' => optional($parent)->getKey(), + ]); } + $lock->release(); + if (null === $stamp) { throw new ModelNotFoundException(); }