diff --git a/bin/create-missing-schedules b/bin/create-missing-schedules new file mode 100644 index 0000000000..41750b163c --- /dev/null +++ b/bin/create-missing-schedules @@ -0,0 +1,3 @@ +#!/bin/sh + +php /usr/src/code/app/cli.php create-missing-schedules $@ \ No newline at end of file diff --git a/src/Appwrite/Platform/Services/Tasks.php b/src/Appwrite/Platform/Services/Tasks.php index 2968a66b95..e6919f2cc7 100644 --- a/src/Appwrite/Platform/Services/Tasks.php +++ b/src/Appwrite/Platform/Services/Tasks.php @@ -8,6 +8,7 @@ use Appwrite\Platform\Tasks\Install; use Appwrite\Platform\Tasks\Maintenance; use Appwrite\Platform\Tasks\Migrate; use Appwrite\Platform\Tasks\Schedule; +use Appwrite\Platform\Tasks\CreateMissingSchedules; use Appwrite\Platform\Tasks\SDKs; use Appwrite\Platform\Tasks\Specs; use Appwrite\Platform\Tasks\SSL; @@ -29,6 +30,7 @@ class Tasks extends Service ->addAction(Doctor::getName(), new Doctor()) ->addAction(Install::getName(), new Install()) ->addAction(Maintenance::getName(), new Maintenance()) + ->addAction(CreateMissingSchedules::getName(), new CreateMissingSchedules()) ->addAction(Schedule::getName(), new Schedule()) ->addAction(Migrate::getName(), new Migrate()) ->addAction(SDKs::getName(), new SDKs()) diff --git a/src/Appwrite/Platform/Tasks/CreateMissingSchedules.php b/src/Appwrite/Platform/Tasks/CreateMissingSchedules.php new file mode 100644 index 0000000000..75e1d5b637 --- /dev/null +++ b/src/Appwrite/Platform/Tasks/CreateMissingSchedules.php @@ -0,0 +1,97 @@ +desc('Ensure every function has a schedule') + ->inject('dbForConsole') + ->inject('getProjectDB') + ->callback(fn (Database $dbForConsole, callable $getProjectDB) => $this->action($dbForConsole, $getProjectDB)); + } + + /** + * Iterate over every function on every project to make sure there is a schedule. If not, recreate the schedule. + */ + public function action(Database $dbForConsole, callable $getProjectDB): void + { + Authorization::disable(); + Authorization::setDefaultStatus(false); + + Console::title('CreateMissingSchedules V1'); + Console::success(APP_NAME . ' CreateMissingSchedules v1 has started'); + + $limit = 100; + $projectCursor = null; + while (true) { + $projectsQueries = [Query::limit($limit)]; + if ($projectCursor !== null) { + $projectsQueries[] = Query::cursorAfter($projectCursor); + } + $projects = $dbForConsole->find('projects', $projectsQueries); + + if (count($projects) === 0) { + break; + } + + foreach ($projects as $project) { + Console::log("Checking Project " . $project->getAttribute('name') . " (" . $project->getId() . ")"); + $dbForProject = $getProjectDB($project); + $functionCursor = null; + + while (true) { + $functionsQueries = [Query::limit($limit)]; + if ($functionCursor !== null) { + $functionsQueries[] = Query::cursorAfter($functionCursor); + } + $functions = $dbForProject->find('functions', $functionsQueries); + if (count($functions) === 0) { + break; + } + + foreach ($functions as $function) { + $scheduleId = $function->getAttribute('scheduleId'); + $schedule = $dbForConsole->getDocument('schedules', $scheduleId); + + if ($schedule->isEmpty()) { + $functionId = $function->getId(); + $schedule = $dbForConsole->createDocument('schedules', new Document([ + '$id' => ID::custom($scheduleId), + 'region' => $project->getAttribute('region', 'default'), + 'resourceType' => 'function', + 'resourceId' => $functionId, + 'resourceUpdatedAt' => DateTime::now(), + 'projectId' => $project->getId(), + 'schedule' => $function->getAttribute('schedule'), + 'active' => !empty($function->getAttribute('schedule')) && !empty($function->getAttribute('deployment')), + ])); + + Console::success('Recreated schedule for function ' . $functionId); + } + } + + $functionCursor = $functions[array_key_last($functions)]; + } + } + + $projectCursor = $projects[array_key_last($projects)]; + } + } +}