From 167a87be6b963ae2519e3fff909270e6ef1f3e4e Mon Sep 17 00:00:00 2001 From: Lucas Graciano Date: Mon, 5 Apr 2021 10:39:26 -0700 Subject: [PATCH] fixed races during process row creation using Laravel's upsert. (#23) Co-authored-by: Paul Rogers --- src/ProcessStamp.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ProcessStamp.php b/src/ProcessStamp.php index a19c70f..d419e67 100644 --- a/src/ProcessStamp.php +++ b/src/ProcessStamp.php @@ -59,21 +59,21 @@ public static function firstOrCreateByProcess(array $process, ?string $hash = nu $parent = static::firstOrCreateByProcess(static::getProcessName($process['type'], $process['parent_name'])); } - $stamp = static::where('hash', $hash)->first(); - - /* - * 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], [ + // Workaround races with `firstOrCreate` by leveraging a no-change upsert. + // NOTE: Not using `insertOrIgnore` because of possible side-effects. + static::upsert( + [ + [ + 'hash' => $hash, 'name' => trim($process['name']), 'type' => $process['type'], 'parent_id' => optional($parent)->getKey(), - ]); - }); - } + ], + ], + ['hash'], // Should be unique to hash. + [] // Update nothing. + ); + $stamp = static::where('hash', $hash)->first(); return $stamp; }