$data * @return array */ public static function storable(array $data): array { return array_filter( Arr::only($data, self::KEYS), fn ($value): bool => is_string($value) || is_int($value), ); } /** * The cleanup data stored on an import activity, or null if the activity has no usable data. * * @return array|null */ public static function stored(Activity $activity): ?array { $data = data_get($activity, 'properties.'.self::PROPERTY); if (! is_array($data)) { return null; } $data = self::storable($data); if (! is_int($data['serverId'] ?? null) || ! Str::isUuid($data['operationUuid'] ?? null)) { return null; } return $data; } public static function stopRequested(Activity $activity): bool { return filled(data_get($activity, 'properties.'.self::STOP_REQUESTED_PROPERTY)); } /** * Queue the stop of the remote restore and the cleanup. It does not run SSH commands * inline, so it is safe during boot. Errors are logged and do not stop the caller. * * @param array $data */ public static function queueStop(array $data): void { try { event(new DatabaseImportFinished([...$data, 'stopRestore' => true])); } catch (Throwable $exception) { Log::warning('Could not queue the stop of an interrupted database import', [ 'operationUuid' => $data['operationUuid'] ?? null, 'serverId' => $data['serverId'] ?? null, 'error' => $exception->getMessage(), ]); } } public static function claimKey(string $operationUuid): string { return "database-import-cleanup:{$operationUuid}"; } /** * Only the first caller for an operation gets true, so the cleanup runs at most once per import. */ public static function claim(string $operationUuid): bool { return Cache::add(self::claimKey($operationUuid), true, self::CLAIM_TTL_SECONDS); } /** * Release the claim after a failed attempt, so a retry of the cleanup can run. */ public static function release(string $operationUuid): void { Cache::forget(self::claimKey($operationUuid)); } }