aboutsummaryrefslogtreecommitdiffstats
path: root/core/Controller/AsyncProcessController.php
diff options
context:
space:
mode:
authorMaxence Lange <maxence@artificial-owl.com>2025-04-28 19:57:56 -0100
committerMaxence Lange <maxence@artificial-owl.com>2025-04-28 19:58:06 -0100
commit6d272ff894fa969e5a526caf6a91d60eda115c53 (patch)
treedf90f826a29f7169dd9b550f2e478a1b09d29e71 /core/Controller/AsyncProcessController.php
parent10a01423ecfc7e028960eee8058bd177ad28d484 (diff)
downloadnextcloud-server-enh/noid/async-process-run.tar.gz
nextcloud-server-enh/noid/async-process-run.zip
feat(async): AsyncProcessenh/noid/async-process-run
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
Diffstat (limited to 'core/Controller/AsyncProcessController.php')
-rw-r--r--core/Controller/AsyncProcessController.php77
1 files changed, 77 insertions, 0 deletions
diff --git a/core/Controller/AsyncProcessController.php b/core/Controller/AsyncProcessController.php
new file mode 100644
index 00000000000..f644e3a7851
--- /dev/null
+++ b/core/Controller/AsyncProcessController.php
@@ -0,0 +1,77 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+namespace OC\Core\Controller;
+
+use OC\Async\Exceptions\BlockAlreadyRunningException;
+use OC\Async\ForkManager;
+use OC\Config\Lexicon\CoreConfigLexicon;
+use OCP\AppFramework\Controller;
+use OCP\AppFramework\Http\Attribute\FrontpageRoute;
+use OCP\AppFramework\Http\Attribute\NoAdminRequired;
+use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
+use OCP\AppFramework\Http\Attribute\PublicPage;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\Async\Enum\ProcessExecutionTime;
+use OCP\IAppConfig;
+use OCP\IRequest;
+
+class AsyncProcessController extends Controller {
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ private IAppConfig $appConfig,
+ private ForkManager $forkManager,
+ ) {
+ parent::__construct($appName, $request);
+ }
+
+ #[NoAdminRequired]
+ #[NoCSRFRequired]
+ #[PublicPage]
+ #[FrontpageRoute(verb: 'POST', url: '/core/asyncProcessFork')]
+ public function processFork(string $token): DataResponse {
+ $metadata = ['executionTime' => ProcessExecutionTime::NOW];
+
+ // remote might only need a confirmation that this is a valid loopback endpoint
+ if ($token === '__ping__') {
+ return new DataResponse(['ping' => $this->appConfig->getValueString('core', CoreConfigLexicon::ASYNC_LOOPBACK_PING)]);
+ }
+
+ $this->async($token);
+
+ try {
+ $this->forkManager->runSession($token, $metadata);
+ } catch (BlockAlreadyRunningException) {
+ // TODO: debug() ?
+ }
+
+ exit();
+ }
+
+ private function async(string $result = ''): void {
+ if (ob_get_contents() !== false) {
+ ob_end_clean();
+ }
+
+ header('Connection: close');
+ header('Content-Encoding: none');
+ ignore_user_abort();
+ $timeLimit = 100;
+ set_time_limit(max($timeLimit, 0));
+ ob_start();
+
+ echo($result);
+
+ $size = ob_get_length();
+ header('Content-Length: ' . $size);
+ ob_end_flush();
+ flush();
+ }
+
+}