Nombres que un reintento no puede dejar huerfanos
La guarda anterior tiene un hueco, y merece nombrarse con honestidad: sólo funciona si la escritura que registra la respuesta de la hoja llegó a aterrizar. Si el worker muere entre que el servicio hoja confirma el éxito y api-server persiste ese hecho, no hay nada en los metadatos contra lo que comprobar. El siguiente intento parece exactamente el primero. Si lo dejas solo, vuelve a llamar a crear, y ahora hay dos recursos al otro lado sin ningún registro local que conecte ninguno con este sitio.
El arreglo no es una guarda mejor. Es eliminar la necesidad de una, haciendo que el propio nombre del recurso sea el registro.
// app/Jobs/RepositoryCreateJob.php
// Deterministic repo name derived from the site's (UUID) id, not a
// timestamp: a retry reuses the same name instead of creating a second,
// orphaned repo when a prior attempt created the repo on GitHub but the
// response was lost. The single repo's name is therefore known to the
// teardown (SiteDeactivationJob) for cleanup.
$repoName = (string) preg_replace(
'/[^A-Za-z0-9\-]/',
'',
Str::of(collect(['name' => $name, 'id' => $this->site->id])->implode('-'))->lower()->replace(' ', '-')->toString()
);
Contrástalo con la versión que sale natural si aún no estás pensando en reintentos:
// Bad: a name that changes on every attempt
$repoName = Str::slug($name.'-'.now()->timestamp);
// retry #2, three minutes later, derives a different name and creates a
// second repository the first attempt's failure left no trace of
La versión con marca de tiempo es el código más obvio de escribir. También es aquel en el que cada reintento es una identidad nueva, libre de dejar atrás lo que el intento anterior ya construyó. La versión determinista siembra el nombre enteramente desde el identificador del sitio: algo que ya existe, ya es único y no cambia entre el primer intento y el quinto. Reinténtalo una vez o diez: el nombre derivado es la misma cadena siempre.
Esta es la misma idea que la guarda de metadatos, apuntada al otro modo de fallo. Esa guarda te protege cuando la escritura local tiene éxito. El nombrado determinista te protege cuando no lo tiene, asegurando que un reintento que ha perdido por completo la pista de lo que pasó la vez anterior siga sin poder crear un duplicado. Un nombre que un sistema genera nuevo en cada intento es un nombre que convierte una caída en un huérfano. Un nombre que un sistema deriva de algo estable convierte esa misma caída en una operación nula.