Example #1
0
 /**
  * Force deletion on a cached resource.
  *
  * @param {string} $key Identifier of target cache.
  * @param {?string} $hash Target revision to delete, all revisions will be deleted if omitted.
  */
 public static function delete($key, $hash = '*')
 {
     $res = self::resolve($key, $hash);
     // Skip the delete if nothing is found.
     if ($res === null) {
         return;
     }
     if ($res->isFile()) {
         // Remove target revision(s).
         if (!$res->isWritable()) {
             Log::warning('Target file is not writable, deletion skipped.');
         } else {
             $path = $res->getRealPath();
             unlink($path);
             $path = dirname($path);
             // Remove the directory if empty.
             $res = new \RecursiveDirectoryIterator($path, \FilesystemIterator::KEY_AS_PATHNAME | \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::SKIP_DOTS);
             if ($res->isDir() && !$res->hasChildren()) {
                 rmdir($path);
             }
         }
     } else {
         if ($res->isDir()) {
             $cacheDirectory = $res->getRealPath();
             foreach ($res as $file) {
                 if ($file->isFile()) {
                     unlink($file->getRealPath());
                 } else {
                     if ($file->isDir()) {
                         rmdir($file->getRealPath());
                     }
                 }
             }
             rmdir($cacheDirectory);
         }
     }
 }
Example #2
0
    Database::unlockTables(true);
    Database::rollback();
    Log::debug('No more jobs to do, suicide.');
    die;
}
$processContents = (array) ContentDecoder::json($process[Node::FIELD_VIRTUAL], 1);
unset($process[Node::FIELD_VIRTUAL]);
$process += $processContents;
unset($processContents);
$res = Database::query('UPDATE `' . FRAMEWORK_COLLECTION_PROCESS . '` SET `pid` = ?
    WHERE `id` = ? AND `pid` IS NULL LIMIT 1', [getmypid(), $process['id']]);
// Commit transaction
Database::unlockTables(true);
Database::commit();
if ($res->rowCount() < 1) {
    Log::warning('Unable to update process pid, worker exits.');
    die;
} else {
    $process['pid'] = getmypid();
    $process[Node::FIELD_COLLECTION] = FRAMEWORK_COLLECTION_PROCESS;
}
// Check if $env specified in option
if (@$_SERVER['env']) {
    $_SERVER['env'] = ContentDecoder::json($_SERVER['env'], 1);
}
// More debug logs
Log::debug("Execute process: {$process['command']}");
// Spawn process and retrieve the pid
$proc = false;
do {
    $proc = proc_open($process['command'], array(array('pipe', 'r'), array('pipe', 'w'), array('pipe', 'e')), $pipes, null, @$_SERVER['env']);
Example #3
0
 /**
  * Process next task with POST data.
  */
 public function process()
 {
     // note: Some tasks can work without post data, but request method must be POST.
     if (!$this->__isSuperUser && $this->__request->method() != 'post') {
         $this->__response->status(405);
         // Method not allowed
         return;
     }
     // WorkInstance
     if (!$this->identity()) {
         $this->__response->status(404);
         // WorkInstance not found
         return;
     }
     // TaskInstance
     $instance = $this->nextTask();
     if (!$instance) {
         $this->__response->status(404);
         // TaskInstance not foudn
         return;
     }
     // release mutable lock for work instance initialization.
     $this->_immutable = false;
     // remove tasks to prevent unwanted change.
     $tasks = $this->tasks;
     unset($this->tasks);
     // creates $this->dataStore if not yet.
     if (empty($this->dataStore)) {
         $this->dataStore = array();
     }
     unset($this->lastError);
     // immutable marker to prevent direct modifications to the internal data.
     $this->_immutable = true;
     // note: Send bayeux message to groups with permission to this task.
     $userGroups = $instance->userGroups();
     try {
         // Note: Since $this->dataStore is an array, it is mutable itself.
         $promise = $instance->process();
     } catch (\Exception $e) {
         Log::warning('Task process exception.', array_filter(array('message' => $e->getMessage(), 'code' => $e->getCode(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'trace' => $e->getTrace())));
         $lastError = array('message' => $this->__response->__($e->getMessage()), 'code' => $e->getCode());
         // note: Failure on Headless tasks will revert to previous task.
         if (@$instance->type == 'Headless') {
             $deferred = new Deferred();
             $deferred->reject($lastError['message'], $lastError['code']);
             $promise = $deferred->promise();
             unset($deferred);
         } else {
             $this->_immutable = false;
             $this->lastError = $lastError;
         }
         unset($lastError);
     }
     $this->_immutable = false;
     $result = array();
     $saveFunc = function () use(&$result) {
         unset($this->timestamp);
         $this->save($result);
     };
     if (isset($promise)) {
         // note: rejection here means revert to previous task
         $promise->fail(function ($error, $code = null) use($instance, $tasks) {
             $this->lastError = array_filter(array('message' => $error, 'code' => $code));
             // revert to previous task
             $prevTask = array_search($instance->identity(), array_map(invokes('identity'), $tasks));
             $prevTask = @$tasks[$prevTask - 1];
             // fallback to the first task
             if (!$prevTask) {
                 $prevTask = reset($tasks);
             }
             $this->nextTask = util::packUuid($prevTask->identity());
         });
         // note: resolution always advances to next task
         $promise->done(function () use($instance, $tasks) {
             $nextTask = array_search($instance->identity(), array_map(invokes('identity'), $tasks));
             $nextTask = @$tasks[$nextTask + 1];
             if ($nextTask) {
                 $this->nextTask = util::packUuid($nextTask->identity());
             } else {
                 $this->state = static::STATE_CLOSE;
                 $this->nextTask = null;
             }
         });
         // note: controller script must call resolve() or reject() to make this happen.
         $promise->always($saveFunc);
     } else {
         $saveFunc();
     }
     unset($saveFunc);
     // note: Merge user groups before and after task processing
     if ($this->nextTask) {
         $userGroups = array_unique(array_merge($userGroups, $this->nextTask()->userGroups()));
     }
     foreach ($userGroups as $userGroup) {
         Bayeux::sendMessage("/group/{$userGroup}", array('action' => 'update', '@collection' => 'WorkInstance', 'timestamp' => $this->timestamp));
     }
     if (@$result['error']) {
         $this->__response->status(500);
         return $result;
     } else {
         // note; User might no longer has access to the updated work instance.
         if ($this->data()) {
             $this->__response->status(200);
             return $this;
         } else {
             $this->__response->status(204);
         }
     }
 }