diff --git a/src/Contracts/Queue/ConnectionFactory.php b/src/Contracts/Queue/ConnectionFactory.php new file mode 100644 index 00000000..0cde9070 --- /dev/null +++ b/src/Contracts/Queue/ConnectionFactory.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * Builds a Context: the entry point of every adapter. + */ +interface ConnectionFactory +{ + /** + * Creates a context (a session/connection to the transport). + * + * @return Context + */ + public function createContext(): Context; +} diff --git a/src/Contracts/Queue/Consumer.php b/src/Contracts/Queue/Consumer.php new file mode 100644 index 00000000..825c7d24 --- /dev/null +++ b/src/Contracts/Queue/Consumer.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * Receives messages from a single queue. + */ +interface Consumer +{ + /** + * Acknowledges the message; the transport may then discard it. + * + * @param Message $message + * @return void + */ + public function acknowledge(Message $message): void; + + /** + * Returns the queue this consumer reads from. + * + * @return Queue + */ + public function getQueue(): Queue; + + /** + * Receives a message, blocking up to timeout milliseconds (0 = block + * until one is available). Returns null when none arrives in time. + * + * @param int $timeout + * @return Message|null + */ + public function receive(int $timeout = 0): Message|null; + + /** + * Receives a message without blocking, or null when none is ready. + * + * @return Message|null + */ + public function receiveNoWait(): Message|null; + + /** + * Rejects the message. When requeue is true the transport redelivers it. + * + * @param Message $message + * @param bool $requeue + * @return void + */ + public function reject(Message $message, bool $requeue = false): void; +} diff --git a/src/Contracts/Queue/Context.php b/src/Contracts/Queue/Context.php new file mode 100644 index 00000000..032a8377 --- /dev/null +++ b/src/Contracts/Queue/Context.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * A session with the transport. Factory for messages, destinations, + * producers and consumers. + */ +interface Context +{ + /** + * Closes the context and releases its resources. + * + * @return void + */ + public function close(): void; + + /** + * Creates a consumer for the given destination. + * + * @param Destination $destination + * @return Consumer + */ + public function createConsumer(Destination $destination): Consumer; + + /** + * Creates a message with an optional body, properties and headers. + * + * @param string $body + * @param array $properties + * @param array $headers + * @return Message + */ + public function createMessage(string $body = '', array $properties = [], array $headers = []): Message; + + /** + * Creates a producer. + * + * @return Producer + */ + public function createProducer(): Producer; + + /** + * Creates a queue destination by name. + * + * @param string $queueName + * @return Queue + */ + public function createQueue(string $queueName): Queue; + + /** + * Creates a subscription consumer for consuming from several queues. + * + * @return SubscriptionConsumer + */ + public function createSubscriptionConsumer(): SubscriptionConsumer; + + /** + * Creates a temporary queue tied to the lifetime of the context. + * + * @return Queue + */ + public function createTemporaryQueue(): Queue; + + /** + * Creates a topic destination by name. + * + * @param string $topicName + * @return Topic + */ + public function createTopic(string $topicName): Topic; + + /** + * Removes all messages from the given queue. + * + * @param Queue $queue + * @return void + */ + public function purgeQueue(Queue $queue): void; +} diff --git a/src/Contracts/Queue/Destination.php b/src/Contracts/Queue/Destination.php new file mode 100644 index 00000000..2de3ff71 --- /dev/null +++ b/src/Contracts/Queue/Destination.php @@ -0,0 +1,17 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * Marker interface for a message destination: a Queue or a Topic. + */ +interface Destination +{ +} diff --git a/src/Contracts/Queue/Message.php b/src/Contracts/Queue/Message.php new file mode 100644 index 00000000..f0400b60 --- /dev/null +++ b/src/Contracts/Queue/Message.php @@ -0,0 +1,173 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * A message exchanged through the transport. Carries a body, application + * properties, transport headers and the standard messaging metadata. + */ +interface Message +{ + /** + * Returns the message body. + * + * @return string + */ + public function getBody(): string; + + /** + * Returns the correlation id used to correlate request/reply messages. + * + * @return string|null + */ + public function getCorrelationId(): string|null; + + /** + * Returns a single header value, or the default when it is not set. + * + * @param string $name + * @param mixed $defaultValue + * @return mixed + */ + public function getHeader(string $name, $defaultValue = null): mixed; + + /** + * Returns all transport headers. + * + * @return array + */ + public function getHeaders(): array; + + /** + * Returns the message id. + * + * @return string|null + */ + public function getMessageId(): string|null; + + /** + * Returns all application properties. + * + * @return array + */ + public function getProperties(): array; + + /** + * Returns a single property value, or the default when it is not set. + * + * @param string $name + * @param mixed $defaultValue + * @return mixed + */ + public function getProperty(string $name, $defaultValue = null): mixed; + + /** + * Returns the reply-to destination name. + * + * @return string|null + */ + public function getReplyTo(): string|null; + + /** + * Returns the timestamp (in milliseconds) or null when it is not set. + * + * @return int|null + */ + public function getTimestamp(): int|null; + + /** + * Whether the message has been redelivered. + * + * @return bool + */ + public function isRedelivered(): bool; + + /** + * Sets the message body. + * + * @param string $body + * @return void + */ + public function setBody(string $body): void; + + /** + * Sets the correlation id. + * + * @param string $correlationId + * @return void + */ + public function setCorrelationId(string $correlationId): void; + + /** + * Sets a single transport header. + * + * @param string $name + * @param mixed $value + * @return void + */ + public function setHeader(string $name, $value): void; + + /** + * Replaces all transport headers. + * + * @param array $headers + * @return void + */ + public function setHeaders(array $headers): void; + + /** + * Sets the message id. + * + * @param string $messageId + * @return void + */ + public function setMessageId(string $messageId): void; + + /** + * Replaces all application properties. + * + * @param array $properties + * @return void + */ + public function setProperties(array $properties): void; + + /** + * Sets a single application property. + * + * @param string $name + * @param mixed $value + * @return void + */ + public function setProperty(string $name, $value): void; + + /** + * Marks the message as redelivered. + * + * @param bool $redelivered + * @return void + */ + public function setRedelivered(bool $redelivered): void; + + /** + * Sets the reply-to destination name. + * + * @param string $replyTo + * @return void + */ + public function setReplyTo(string $replyTo): void; + + /** + * Sets the timestamp (in milliseconds). + * + * @param int $timestamp + * @return void + */ + public function setTimestamp(int $timestamp): void; +} diff --git a/src/Contracts/Queue/Processor.php b/src/Contracts/Queue/Processor.php new file mode 100644 index 00000000..182f0bee --- /dev/null +++ b/src/Contracts/Queue/Processor.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * Processes a single message. The return value tells the consumer what to + * do next: acknowledge, reject, or requeue. + * + * The literal constant values are kept compatible with the wider interop + * ecosystem. + */ +interface Processor +{ + /** + * @var string + */ + const string ACK = 'enqueue.ack'; + + /** + * @var string + */ + const string REJECT = 'enqueue.reject'; + + /** + * @var string + */ + const string REQUEUE = 'enqueue.requeue'; + + + /** + * Processes the message and returns one of the ACK / REJECT / REQUEUE + * constants, or an object whose string form is one of those values. + * + * @return string|object + * @param Message $message + * @param Context $context + */ + public function process(Message $message, Context $context): object|string; +} diff --git a/src/Contracts/Queue/Producer.php b/src/Contracts/Queue/Producer.php new file mode 100644 index 00000000..8ec60846 --- /dev/null +++ b/src/Contracts/Queue/Producer.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * Sends messages to a destination. + */ +interface Producer +{ + /** + * Returns the delivery delay (in milliseconds) or null when not set. + * + * @return int|null + */ + public function getDeliveryDelay(): int|null; + + /** + * Returns the message priority or null when not set. + * + * @return int|null + */ + public function getPriority(): int|null; + + /** + * Returns the time to live (in milliseconds) or null when not set. + * + * @return int|null + */ + public function getTimeToLive(): int|null; + + /** + * Sends a message to the given destination. + * + * @param Destination $destination + * @param Message $message + * @return void + */ + public function send(Destination $destination, Message $message): void; + + /** + * Sets the delivery delay (in milliseconds). Null clears it. + * + * @param mixed $deliveryDelay + * @return Producer + */ + public function setDeliveryDelay($deliveryDelay = null): Producer; + + /** + * Sets the message priority. Null clears it. + * + * @param mixed $priority + * @return Producer + */ + public function setPriority($priority = null): Producer; + + /** + * Sets the time to live (in milliseconds). Null clears it. + * + * @param mixed $timeToLive + * @return Producer + */ + public function setTimeToLive($timeToLive = null): Producer; +} diff --git a/src/Contracts/Queue/Queue.php b/src/Contracts/Queue/Queue.php new file mode 100644 index 00000000..d2b6dd6e --- /dev/null +++ b/src/Contracts/Queue/Queue.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * A queue destination (point-to-point). + */ +interface Queue extends \Phalcon\Contracts\Queue\Destination +{ + /** + * Returns the queue name. + * + * @return string + */ + public function getQueueName(): string; +} diff --git a/src/Contracts/Queue/SubscriptionConsumer.php b/src/Contracts/Queue/SubscriptionConsumer.php new file mode 100644 index 00000000..55ff4186 --- /dev/null +++ b/src/Contracts/Queue/SubscriptionConsumer.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * Consumes from several queues at once, dispatching each message to the + * callback registered for its consumer. + */ +interface SubscriptionConsumer +{ + /** + * Starts consuming, blocking up to timeout milliseconds (0 = block + * until a message is available). + * + * @param int $timeout + * @return void + */ + public function consume(int $timeout = 0): void; + + /** + * Subscribes a consumer; the callback receives each delivered message. + * + * @param Consumer $consumer + * @param callable $callback + * @return void + */ + public function subscribe(Consumer $consumer, $callback): void; + + /** + * Removes a previously subscribed consumer. + * + * @param Consumer $consumer + * @return void + */ + public function unsubscribe(Consumer $consumer): void; + + /** + * Removes every subscribed consumer. + * + * @return void + */ + public function unsubscribeAll(): void; +} diff --git a/src/Contracts/Queue/Topic.php b/src/Contracts/Queue/Topic.php new file mode 100644 index 00000000..e2e7b9c9 --- /dev/null +++ b/src/Contracts/Queue/Topic.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * A topic destination (publish/subscribe). + */ +interface Topic extends \Phalcon\Contracts\Queue\Destination +{ + /** + * Returns the topic name. + * + * @return string + */ + public function getTopicName(): string; +} diff --git a/src/Contracts/Queue/VisibilityAware.php b/src/Contracts/Queue/VisibilityAware.php new file mode 100644 index 00000000..8a23b012 --- /dev/null +++ b/src/Contracts/Queue/VisibilityAware.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Queue; + +/** + * Marker contract for a consumer that supports a visibility timeout + * (for example Beanstalk TTR or an SQS visibility timeout). Callers detect + * support with `instanceof`. It carries no behavior and commits to no class + * shape. + */ +interface VisibilityAware +{ +} diff --git a/src/Contracts/Support/Debug/Renderer.php b/src/Contracts/Support/Debug/Renderer.php new file mode 100644 index 00000000..5a56e728 --- /dev/null +++ b/src/Contracts/Support/Debug/Renderer.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Support\Debug; + +use Phalcon\Support\Debug\Report\ExceptionReport; + +/** + * Canonical contract for Phalcon\Support\Debug renderers. Turns an + * ExceptionReport into output. + */ +interface Renderer extends \Phalcon\Contracts\Support\Debug\TemplateAware +{ + /** + * Returns the CSS sources block for the given base URI. + * + * @param string $uri + * + * @return string + */ + public function getCssSources(string $uri): string; + + /** + * Returns the JavaScript sources block for the given base URI. + * + * @param string $uri + * + * @return string + */ + public function getJsSources(string $uri): string; + + /** + * Returns the framework version block. + * + * @return string + */ + public function getVersion(): string; + + /** + * Renders the report. + * + * @param ExceptionReport $report + * + * @return string + */ + public function render(\Phalcon\Support\Debug\Report\ExceptionReport $report): string; +} diff --git a/src/Contracts/Support/Debug/TemplateAware.php b/src/Contracts/Support/Debug/TemplateAware.php new file mode 100644 index 00000000..b1f9eac1 --- /dev/null +++ b/src/Contracts/Support/Debug/TemplateAware.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Contracts\Support\Debug; + +/** + * Canonical contract for components that render through named, overridable + * template strings. + */ +interface TemplateAware +{ + /** + * Returns the template for the given name (override if set, default + * otherwise). + * + * @param string $name + * + * @return string + */ + public function getTemplate(string $name): string; + + /** + * Overrides the template for the given name. + * + * @param string $name + * @param string $template + * + * @return static + */ + public function setTemplate(string $name, string $template): static; +} diff --git a/src/DataMapper/Pdo/Connection/AbstractConnection.php b/src/DataMapper/Pdo/Connection/AbstractConnection.php index 87e2d583..974c7ff0 100644 --- a/src/DataMapper/Pdo/Connection/AbstractConnection.php +++ b/src/DataMapper/Pdo/Connection/AbstractConnection.php @@ -19,6 +19,14 @@ */ abstract class AbstractConnection implements \Phalcon\DataMapper\Pdo\Connection\ConnectionInterface { + /** + * Whether to transparently reconnect and retry once when a statement fails + * because the connection was lost. Opt-in; off by default. + * + * @var bool + */ + protected $autoReconnect = false; + /** * @var \PDO */ @@ -29,6 +37,15 @@ abstract class AbstractConnection implements \Phalcon\DataMapper\Pdo\Connection\ */ protected $profiler; + /** + * Current transaction nesting level. Tracked locally rather than via + * PDO::inTransaction() because some drivers report a broken connection as + * being "in transaction". + * + * @var int + */ + protected $transactionLevel = 0; + /** * Proxies to PDO methods created for specific drivers; in particular, * `sqlite` and `pgsql`. @@ -77,6 +94,17 @@ abstract public function connect(): void; */ abstract public function disconnect(): void; + /** + * Ensures the connection is alive, reconnecting in place if it is not. + * disconnect() is required first because connect() is idempotent and will + * not rebuild a dead-but-present handle. + * + * @return void + */ + public function ensureConnection(): void + { + } + /** * Gets the most recent error code. * @@ -287,6 +315,15 @@ public static function getAvailableDrivers(): array { } + /** + * Returns whether transparent auto-reconnect is enabled. + * + * @return bool + */ + public function getAutoReconnect(): bool + { + } + /** * Return the driver name * @@ -363,6 +400,16 @@ public function perform(string $statement, array $values = []): \PDOStatement { } + /** + * Checks whether the underlying connection is still alive by issuing a + * trivial query. Returns false if there is no handle or the probe fails. + * + * @return bool + */ + public function ping(): bool + { + } + /** * Prepares an SQL statement for execution. * @@ -424,6 +471,16 @@ public function setAttribute(int $attribute, $value): bool { } + /** + * Enables or disables transparent auto-reconnect on a lost connection. + * + * @param bool $autoReconnect + * @return static + */ + public function setAutoReconnect(bool $autoReconnect): static + { + } + /** * Sets the Profiler instance. * @@ -459,4 +516,50 @@ protected function performBind(\PDOStatement $statement, $name, $arguments): voi protected function fetchData(string $method, array $arguments, string $statement, array $values = []): array { } + + /** + * Recognizes a lost ("gone away") connection. Detection is driver-agnostic: + * the driver name is not queried because the underlying connection may be + * dead by this point. The MySQL error codes and PostgreSQL SQLSTATEs do not + * overlap, so all known signatures are checked unconditionally. + * + * @param \Throwable $exception + * @return bool + */ + protected function isConnectionError(\Throwable $exception): bool + { + } + + /** + * Whether a failed statement may be transparently retried after + * reconnecting. Only when auto-reconnect is on, a handle exists, we are + * not in a transaction, and the failure is a recognized connection loss. + * + * @param \Throwable $exception + * @return bool + */ + private function canReconnect(\Throwable $exception): bool + { + } + + /** + * Prepares, binds, and executes a statement, returning the PDOStatement. + * + * @param string $statement + * @param array $values + * @return \PDOStatement + */ + private function performStatement(string $statement, array $values): \PDOStatement + { + } + + /** + * Drops the dead handle and rebuilds it. disconnect() first is required + * because connect() is idempotent. + * + * @return void + */ + private function reconnect(): void + { + } } diff --git a/src/Db/Adapter/Pdo/AbstractPdo.php b/src/Db/Adapter/Pdo/AbstractPdo.php index 6bfd2bb6..4e781ead 100644 --- a/src/Db/Adapter/Pdo/AbstractPdo.php +++ b/src/Db/Adapter/Pdo/AbstractPdo.php @@ -53,6 +53,14 @@ abstract class AbstractPdo extends AbstractAdapter */ protected $affectedRows = 0; + /** + * Whether to transparently reconnect and retry once when a query fails + * because the connection was lost. Opt-in; off by default. + * + * @var bool + */ + protected $autoReconnect = false; + /** * PDO Handler * @@ -195,6 +203,15 @@ public function escapeString(string $str): string { } + /** + * Ensures the connection is alive, reconnecting in place if it is not. + * + * @return void + */ + public function ensureConnection(): void + { + } + /** * Sends SQL statements to the database server returning the success state. * Use this method only when the SQL statement sent to the server does not @@ -255,6 +272,15 @@ public function executePrepared(\PDOStatement $statement, array $placeholders, a { } + /** + * Returns whether transparent auto-reconnect is enabled. + * + * @return bool + */ + public function getAutoReconnect(): bool + { + } + /** * Return the error info, if any * @@ -329,6 +355,16 @@ public function lastInsertId(?string $name = null): bool|string { } + /** + * Checks whether the underlying connection is still alive by issuing a + * trivial query. Returns false if there is no handle or the probe fails. + * + * @return bool + */ + public function ping(): bool + { + } + /** * Returns a PDO prepared statement to be executed with 'executePrepared' * @@ -395,6 +431,16 @@ public function rollback(bool $nesting = true): bool { } + /** + * Enables or disables transparent auto-reconnect on a lost connection. + * + * @param bool $autoReconnect + * @return static + */ + public function setAutoReconnect(bool $autoReconnect): static + { + } + /** * Returns PDO adapter DSN defaults as a key-value map. * @@ -402,6 +448,18 @@ public function rollback(bool $nesting = true): bool */ abstract protected function getDsnDefaults(): array; + /** + * Recognizes whether an exception represents a lost ("gone away") + * connection. The base adapter cannot know driver specifics, so it + * returns false; concrete adapters override this. + * + * @param \Throwable $exception + * @return bool + */ + protected function isConnectionError(\Throwable $exception): bool + { + } + /** * Constructs the SQL statement (with parameters) * @@ -413,4 +471,50 @@ abstract protected function getDsnDefaults(): array; protected function prepareRealSql(string $statement, array $parameters): void { } + + /** + * Whether a failed query may be transparently retried after reconnecting. + * Only when auto-reconnect is on, we are not in a transaction, and the + * failure is a recognized connection loss. + * + * @param \Throwable $exception + * @return bool + */ + private function canReconnect(\Throwable $exception): bool + { + } + + /** + * Runs the actual write against PDO and returns the affected-rows count + * (or the raw exec() return for unprepared statements). + * + * @param string $sqlStatement + * @param array $bindParams + * @param array $bindTypes + * @return mixed + */ + private function executeStatement(string $sqlStatement, array $bindParams, array $bindTypes): mixed + { + } + + /** + * Notifies listeners that the connection was lost and re-establishes it. + * + * @return void + */ + private function handleConnectionLost(): void + { + } + + /** + * Prepares and executes a read statement, returning the live PDOStatement. + * + * @param string $sqlStatement + * @param array $params + * @param array $types + * @return \PDOStatement + */ + private function queryStatement(string $sqlStatement, array $params, array $types): \PDOStatement + { + } } diff --git a/src/Db/Adapter/Pdo/Mysql.php b/src/Db/Adapter/Pdo/Mysql.php index e769941c..1859712b 100644 --- a/src/Db/Adapter/Pdo/Mysql.php +++ b/src/Db/Adapter/Pdo/Mysql.php @@ -120,4 +120,15 @@ public function describeReferences(string $table, ?string $schema = null): array protected function getDsnDefaults(): array { } + + /** + * Recognizes a MySQL "server has gone away" / "Lost connection" failure + * by the driver error code (2006 / 2013) with a message fallback. + * + * @param \Throwable $exception + * @return bool + */ + protected function isConnectionError(\Throwable $exception): bool + { + } } diff --git a/src/Db/Adapter/Pdo/Postgresql.php b/src/Db/Adapter/Pdo/Postgresql.php index 7059a4c8..a1d5495a 100644 --- a/src/Db/Adapter/Pdo/Postgresql.php +++ b/src/Db/Adapter/Pdo/Postgresql.php @@ -182,4 +182,16 @@ public function useExplicitIdValue(): bool protected function getDsnDefaults(): array { } + + /** + * Recognizes a PostgreSQL connection-loss failure by SQLSTATE + * (connection exception class 08, or admin/crash shutdown 57P0x) with a + * message fallback. + * + * @param \Throwable $exception + * @return bool + */ + protected function isConnectionError(\Throwable $exception): bool + { + } } diff --git a/src/Queue/Adapter/AbstractConsumer.php b/src/Queue/Adapter/AbstractConsumer.php new file mode 100644 index 00000000..9a223d1f --- /dev/null +++ b/src/Queue/Adapter/AbstractConsumer.php @@ -0,0 +1,94 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Consumer as ConsumerInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; + +/** + * Shared consumer base. Implements the blocking `receive()` as a polling loop + * on top of the abstract `receiveNoWait()`; concrete consumers provide the + * transport-specific `receiveNoWait`, `acknowledge` and `reject`. + * + * Transports with a native blocking receive (Redis BRPOP, Beanstalk reserve) + * override `receive()` instead of polling. + */ +abstract class AbstractConsumer implements ConsumerInterface +{ + /** + * Milliseconds slept between poll attempts. + * + * @var int + */ + protected $pollInterval = 200; + + /** + * The queue this consumer reads from. + * + * @var QueueInterface + */ + protected $queue; + + /** + * Acknowledges the message; the transport may then discard it. + * + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + abstract public function acknowledge(\Phalcon\Contracts\Queue\Message $message): void; + + /** + * Returns the queue this consumer reads from. + * + * @return QueueInterface + */ + public function getQueue(): QueueInterface + { + } + + /** + * Receives a message, blocking up to timeout milliseconds (0 = block + * until one is available), by polling `receiveNoWait()` every + * `pollInterval` milliseconds. Returns null when none arrives in time. + * + * @param int $timeout + * @return MessageInterface|null + */ + public function receive(int $timeout = 0): MessageInterface|null + { + } + + /** + * Receives a message without blocking, or null when none is ready. + * + * @return MessageInterface|null + */ + abstract public function receiveNoWait(): MessageInterface|null; + + /** + * Rejects the message. When requeue is true the transport redelivers it. + * + * @param \Phalcon\Contracts\Queue\Message $message + * @param bool $requeue + * @return void + */ + abstract public function reject(\Phalcon\Contracts\Queue\Message $message, bool $requeue = false): void; + + /** + * Sets the poll interval (in milliseconds) used by `receive()`. + * + * @param int $pollInterval + * @return void + */ + public function setPollInterval(int $pollInterval): void + { + } +} diff --git a/src/Queue/Adapter/AbstractContext.php b/src/Queue/Adapter/AbstractContext.php new file mode 100644 index 00000000..8eb227c2 --- /dev/null +++ b/src/Queue/Adapter/AbstractContext.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Context as ContextInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Contracts\Queue\Topic as TopicInterface; + +/** + * Shared transport-session base. Every transport builds the same destination + * value objects (GenericQueue / GenericTopic) and the same uniquely named + * temporary queue, so those factories live here once. Concrete contexts + * implement the transport-specific factories (consumer, producer, message, + * subscription consumer) and the storage operations. + */ +abstract class AbstractContext implements ContextInterface +{ + /** + * Creates a queue destination by name. + * + * @param string $queueName + * @return QueueInterface + */ + public function createQueue(string $queueName): QueueInterface + { + } + + /** + * Creates a uniquely named temporary queue. + * + * @return QueueInterface + */ + public function createTemporaryQueue(): QueueInterface + { + } + + /** + * Creates a topic destination by name. + * + * @param string $topicName + * @return TopicInterface + */ + public function createTopic(string $topicName): TopicInterface + { + } +} diff --git a/src/Queue/Adapter/AbstractMessage.php b/src/Queue/Adapter/AbstractMessage.php new file mode 100644 index 00000000..26a473b7 --- /dev/null +++ b/src/Queue/Adapter/AbstractMessage.php @@ -0,0 +1,250 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Message as MessageInterface; + +/** + * Shared implementation of every Message getter/setter, plus the + * correlation-id / message-id / timestamp / reply-to header conveniences. + * Concrete adapter messages extend this base. + * + * The convenience accessors are stored as transport headers under fixed keys + * for binary compatibility with the wider interop ecosystem. + */ +abstract class AbstractMessage implements MessageInterface +{ + /** + * @var string + */ + protected $body = ''; + + /** + * @var array + */ + protected $headers = []; + + /** + * @var array + */ + protected $properties = []; + + /** + * @var bool + */ + protected $redelivered = false; + + /** + * AbstractMessage constructor. + * + * @param string $body + * @param array $properties + * @param array $headers + */ + public function __construct(string $body = '', array $properties = [], array $headers = []) + { + } + + /** + * Returns the message body. + * + * @return string + */ + public function getBody(): string + { + } + + /** + * Returns the correlation id used to correlate request/reply messages. + * + * @return string|null + */ + public function getCorrelationId(): string|null + { + } + + /** + * Returns a single header value, or the default when it is not set. + * + * @param string $name + * @param mixed $defaultValue + * @return mixed + */ + public function getHeader(string $name, $defaultValue = null): mixed + { + } + + /** + * Returns all transport headers. + * + * @return array + */ + public function getHeaders(): array + { + } + + /** + * Returns the message id. + * + * @return string|null + */ + public function getMessageId(): string|null + { + } + + /** + * Returns all application properties. + * + * @return array + */ + public function getProperties(): array + { + } + + /** + * Returns a single property value, or the default when it is not set. + * + * @param string $name + * @param mixed $defaultValue + * @return mixed + */ + public function getProperty(string $name, $defaultValue = null): mixed + { + } + + /** + * Returns the reply-to destination name. + * + * @return string|null + */ + public function getReplyTo(): string|null + { + } + + /** + * Returns the timestamp (in milliseconds) or null when it is not set. + * + * @return int|null + */ + public function getTimestamp(): int|null + { + } + + /** + * Whether the message has been redelivered. + * + * @return bool + */ + public function isRedelivered(): bool + { + } + + /** + * Sets the message body. + * + * @param string $body + * @return void + */ + public function setBody(string $body): void + { + } + + /** + * Sets the correlation id. + * + * @param string $correlationId + * @return void + */ + public function setCorrelationId(string $correlationId): void + { + } + + /** + * Sets a single transport header. + * + * @param string $name + * @param mixed $value + * @return void + */ + public function setHeader(string $name, $value): void + { + } + + /** + * Replaces all transport headers. + * + * @param array $headers + * @return void + */ + public function setHeaders(array $headers): void + { + } + + /** + * Sets the message id. + * + * @param string $messageId + * @return void + */ + public function setMessageId(string $messageId): void + { + } + + /** + * Replaces all application properties. + * + * @param array $properties + * @return void + */ + public function setProperties(array $properties): void + { + } + + /** + * Sets a single application property. + * + * @param string $name + * @param mixed $value + * @return void + */ + public function setProperty(string $name, $value): void + { + } + + /** + * Marks the message as redelivered. + * + * @param bool $redelivered + * @return void + */ + public function setRedelivered(bool $redelivered): void + { + } + + /** + * Sets the reply-to destination name. + * + * @param string $replyTo + * @return void + */ + public function setReplyTo(string $replyTo): void + { + } + + /** + * Sets the timestamp (in milliseconds). + * + * @param int $timestamp + * @return void + */ + public function setTimestamp(int $timestamp): void + { + } +} diff --git a/src/Queue/Adapter/AbstractProducer.php b/src/Queue/Adapter/AbstractProducer.php new file mode 100644 index 00000000..0621a30f --- /dev/null +++ b/src/Queue/Adapter/AbstractProducer.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Producer as ProducerInterface; +use Phalcon\Queue\Exceptions\DeliveryDelayNotSupportedException; +use Phalcon\Queue\Exceptions\PriorityNotSupportedException; +use Phalcon\Queue\Exceptions\TimeToLiveNotSupportedException; + +/** + * Shared producer base. Defaults every optional capability (delivery delay, + * priority, time to live) to "unsupported": the getter returns null and the + * setter throws the matching exception for any non-null value. A concrete + * producer overrides only the capabilities its transport actually supports, + * and implements `send()`. + */ +abstract class AbstractProducer implements ProducerInterface +{ + /** + * @return int|null + */ + public function getDeliveryDelay(): int|null + { + } + + /** + * @return int|null + */ + public function getPriority(): int|null + { + } + + /** + * @return int|null + */ + public function getTimeToLive(): int|null + { + } + + /** + * @param \Phalcon\Contracts\Queue\Destination $destination + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + abstract public function send(\Phalcon\Contracts\Queue\Destination $destination, \Phalcon\Contracts\Queue\Message $message): void; + + /** + * @param mixed $deliveryDelay + * @return ProducerInterface + */ + public function setDeliveryDelay($deliveryDelay = null): ProducerInterface + { + } + + /** + * @param mixed $priority + * @return ProducerInterface + */ + public function setPriority($priority = null): ProducerInterface + { + } + + /** + * @param mixed $timeToLive + * @return ProducerInterface + */ + public function setTimeToLive($timeToLive = null): ProducerInterface + { + } +} diff --git a/src/Queue/Adapter/AbstractSubscriptionConsumer.php b/src/Queue/Adapter/AbstractSubscriptionConsumer.php new file mode 100644 index 00000000..b0229a3b --- /dev/null +++ b/src/Queue/Adapter/AbstractSubscriptionConsumer.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Consumer as ConsumerInterface; +use Phalcon\Contracts\Queue\SubscriptionConsumer as SubscriptionConsumerInterface; + +/** + * Shared subscription-consumer base. Implements the round-robin poll loop that + * dispatches each subscribed consumer's messages to its callback; a callback + * returning false stops consumption. The loop relies only on the consumer's + * `receiveNoWait()`, so it is transport-agnostic. Concrete adapters keep just + * the constructor that captures their context and poll interval. + */ +abstract class AbstractSubscriptionConsumer implements SubscriptionConsumerInterface +{ + /** + * Milliseconds slept between poll passes. + * + * @var int + */ + protected $pollInterval = 200; + + /** + * Subscriptions keyed by queue name: [consumer, callback]. + * + * @var array + */ + protected $subscriptions = []; + + /** + * Polls every subscription, dispatching each message to its callback, + * blocking up to timeout milliseconds (0 = block until a callback + * returns false). + * + * @param int $timeout + * @return void + */ + public function consume(int $timeout = 0): void + { + } + + /** + * Subscribes a consumer; the callback receives each delivered message. + * + * @param \Phalcon\Contracts\Queue\Consumer $consumer + * @param callable $callback + * @return void + */ + public function subscribe(\Phalcon\Contracts\Queue\Consumer $consumer, $callback): void + { + } + + /** + * Removes a previously subscribed consumer. + * + * @param \Phalcon\Contracts\Queue\Consumer $consumer + * @return void + */ + public function unsubscribe(\Phalcon\Contracts\Queue\Consumer $consumer): void + { + } + + /** + * Removes every subscribed consumer. + * + * @return void + */ + public function unsubscribeAll(): void + { + } + + /** + * Resolves a consumer's queue name. The `consumer` parameter is typed + * `var` so the call is dynamic; this avoids Zephir resolving the + * Consumer::getQueue() return type's short name in the wrong namespace. + * + * @param mixed $consumer + * @return string + */ + private function resolveQueueName($consumer): string + { + } +} diff --git a/src/Queue/Adapter/Beanstalk/BeanstalkConnection.php b/src/Queue/Adapter/Beanstalk/BeanstalkConnection.php new file mode 100644 index 00000000..bcd642d2 --- /dev/null +++ b/src/Queue/Adapter/Beanstalk/BeanstalkConnection.php @@ -0,0 +1,225 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Beanstalk; + +use Phalcon\Queue\Exceptions\Exception; + +/** + * Dependency-free socket client for the Beanstalkd work queue, implementing + * the subset of the 1.2 protocol the adapter needs (use/watch/ignore, put, + * reserve-with-timeout, delete/release/bury/touch). Recovered and trimmed + * from the original Phalcon\Queue\Beanstalk transport. + */ +class BeanstalkConnection +{ + /** + * Connection resource. + * + * @var resource + */ + protected $connection; + + /** + * @var string + */ + protected $host = '127.0.0.1'; + + /** + * @var bool + */ + protected $persistent = false; + + /** + * @var int + */ + protected $port = 11300; + + /** + * Tube currently selected with `use`. A fresh connection uses "default". + * + * @var string + */ + protected $usedTube = 'default'; + + /** + * Tubes currently on the watch list, keyed by tube name. A fresh + * connection watches "default". + * + * @var array + */ + protected $watchedTubes = []; + + /** + * @param string $host + * @param int $port + * @param bool $persistent + */ + public function __construct(string $host = '127.0.0.1', int $port = 11300, bool $persistent = false) + { + } + + /** + * Puts a reserved job into the "buried" state. + * + * @param string $id + * @param int $priority + * @return bool + */ + public function buryJob(string $id, int $priority): bool + { + } + + /** + * Opens the socket connection to the Beanstalkd server. + * + * @return resource + */ + public function connect() + { + } + + /** + * Removes a job from the server entirely. + * + * @param string $id + * @return bool + */ + public function deleteJob(string $id): bool + { + } + + /** + * Closes the connection to the server. + * + * @return bool + */ + public function disconnect(): bool + { + } + + /** + * Removes the named tube from the watch list for the connection. + * + * @param string $tube + * @return bool + */ + public function ignoreTube(string $tube): bool + { + } + + /** + * Puts a job on the queue using the currently used tube. Returns the new + * job id, or false when the server did not accept it. + * + * @param string $data + * @param int $priority + * @param int $delay + * @param int $ttr + * @return int|bool + */ + public function put(string $data, int $priority, int $delay, int $ttr): int|bool + { + } + + /** + * Reads a packet from the socket. Verifies the connection is available + * first. + * + * @param int $length + * @return bool|string + */ + public function read(int $length = 0): bool|string + { + } + + /** + * Reads the latest status line and splits it into tokens. + * + * @return array + */ + public function readStatus(): array + { + } + + /** + * Puts a reserved job back into the ready queue. + * + * @param string $id + * @param int $priority + * @param int $delay + * @return bool + */ + public function releaseJob(string $id, int $priority, int $delay): bool + { + } + + /** + * Reserves a ready job from a watched tube. A null timeout blocks until a + * job is available; otherwise it blocks up to timeout seconds. Returns + * [id, body] or null when none is reserved. + * + * @param mixed $timeout + * @return array|null + */ + public function reserve($timeout = null): array|null + { + } + + /** + * Extends the time-to-run of a reserved job. + * + * @param string $id + * @return bool + */ + public function touchJob(string $id): bool + { + } + + /** + * Changes the tube new jobs are put on. By default this is "default". + * + * @param string $tube + * @return bool + */ + public function useTube(string $tube): bool + { + } + + /** + * Adds the named tube to the watch list for the connection. + * + * @param string $tube + * @return bool + */ + public function watchTube(string $tube): bool + { + } + + /** + * Writes data to the socket, connecting first when needed. + * + * @param string $data + * @return bool|int + */ + public function write(string $data): int|bool + { + } + + /** + * Re-issues the use/watch/ignore commands after a reconnect so a new + * socket resumes the tube selection the caller established. A fresh + * connection only uses and watches "default". + * + * @return void + */ + private function restoreSession(): void + { + } +} diff --git a/src/Queue/Adapter/Beanstalk/BeanstalkConnectionFactory.php b/src/Queue/Adapter/Beanstalk/BeanstalkConnectionFactory.php new file mode 100644 index 00000000..071adb43 --- /dev/null +++ b/src/Queue/Adapter/Beanstalk/BeanstalkConnectionFactory.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Beanstalk; + +use Phalcon\Contracts\Queue\ConnectionFactory as ConnectionFactoryInterface; +use Phalcon\Contracts\Queue\Context as ContextInterface; + +/** + * Builds a BeanstalkContext. + * + * Options: + * - host: server host (default 127.0.0.1). + * - port: server port (default 11300). + * - persistent: use a persistent socket (default false). + * - ttr: default time-to-run in seconds for every job (default 86400). + * - pollInterval: milliseconds between subscription poll passes (default 200). + */ +class BeanstalkConnectionFactory implements ConnectionFactoryInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * @param array $options + */ + public function __construct(array $options = []) + { + } + + /** + * @return ContextInterface + */ + public function createContext(): ContextInterface + { + } +} diff --git a/src/Queue/Adapter/Beanstalk/BeanstalkConsumer.php b/src/Queue/Adapter/Beanstalk/BeanstalkConsumer.php new file mode 100644 index 00000000..c0ba6762 --- /dev/null +++ b/src/Queue/Adapter/Beanstalk/BeanstalkConsumer.php @@ -0,0 +1,110 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Beanstalk; + +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Contracts\Queue\VisibilityAware; +use Phalcon\Queue\Adapter\AbstractConsumer; +use Phalcon\Queue\Adapter\MessageEnvelope; + +/** + * Receives messages from a single Beanstalkd tube over its own connection. + * `receive()` is overridden to use the native blocking reserve. Implements + * VisibilityAware: a reserved job has a time-to-run window that `touch()` + * extends; acknowledging deletes the job, rejecting releases it (requeue) or + * buries it. + */ +class BeanstalkConsumer extends AbstractConsumer implements \Phalcon\Contracts\Queue\VisibilityAware +{ + /** + * Default Beanstalkd priority used when releasing or burying. + * + * @var int + */ + const int DEFAULT_PRIORITY = 100; + + /** + * @var BeanstalkConnection + */ + protected $connection; + + /** + * @param BeanstalkConnection $connection + * @param \Phalcon\Contracts\Queue\Queue $queue + */ + public function __construct(BeanstalkConnection $connection, \Phalcon\Contracts\Queue\Queue $queue) + { + } + + /** + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function acknowledge(\Phalcon\Contracts\Queue\Message $message): void + { + } + + /** + * @param int $timeout + * @return MessageInterface|null + */ + public function receive(int $timeout = 0): MessageInterface|null + { + } + + /** + * @return MessageInterface|null + */ + public function receiveNoWait(): MessageInterface|null + { + } + + /** + * @param \Phalcon\Contracts\Queue\Message $message + * @param bool $requeue + * @return void + */ + public function reject(\Phalcon\Contracts\Queue\Message $message, bool $requeue = false): void + { + } + + /** + * Extends the time-to-run window of a reserved job (VisibilityAware). + * + * @param \Phalcon\Contracts\Queue\Message $message + * @return bool + */ + public function touch(\Phalcon\Contracts\Queue\Message $message): bool + { + } + + /** + * Builds a BeanstalkMessage from a reserved [id, body] pair, or null. + * + * @param mixed $job + * @return MessageInterface|null + */ + private function buildMessage($job): MessageInterface|null + { + } + + /** + * Resolves a message's Beanstalkd job id. The `message` parameter is typed + * `var` so the call is dynamic; this avoids Zephir resolving getJobId() + * against the Message interface, which does not declare it. + * + * @param mixed $message + * @return string + */ + private function resolveJobId($message): string + { + } +} diff --git a/src/Queue/Adapter/Beanstalk/BeanstalkContext.php b/src/Queue/Adapter/Beanstalk/BeanstalkContext.php new file mode 100644 index 00000000..540e918b --- /dev/null +++ b/src/Queue/Adapter/Beanstalk/BeanstalkContext.php @@ -0,0 +1,165 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Beanstalk; + +use Phalcon\Contracts\Queue\Consumer as ConsumerInterface; +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Producer as ProducerInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Contracts\Queue\SubscriptionConsumer as SubscriptionConsumerInterface; +use Phalcon\Queue\Adapter\AbstractContext; +use Phalcon\Queue\Adapter\QueueDestinationGuard; + +/** + * Beanstalkd transport session. A queue maps to a Beanstalkd tube. Producers + * share the context connection (`use` + `put`); each consumer owns its own + * connection, because Beanstalkd only lets the reserving connection delete, + * release, bury or touch a job. The destination factories come from + * AbstractContext. + */ +class BeanstalkContext extends AbstractContext +{ + /** + * Shared connection used by producers and purges. + * + * @var BeanstalkConnection | null + */ + protected $connection = null; + + /** + * @var string + */ + protected $host = '127.0.0.1'; + + /** + * @var bool + */ + protected $persistent = false; + + /** + * Milliseconds slept between poll passes by a subscription consumer. + * + * @var int + */ + protected $pollInterval = 200; + + /** + * @var int + */ + protected $port = 11300; + + /** + * Default time-to-run (seconds) applied to every put. + * + * @var int + */ + protected $ttr = 86400; + + /** + * @param string $host + * @param int $port + * @param bool $persistent + * @param int $ttr + * @param int $pollInterval + */ + public function __construct(string $host, int $port, bool $persistent = false, int $ttr = 86400, int $pollInterval = 200) + { + } + + /** + * @return void + */ + public function close(): void + { + } + + /** + * @param \Phalcon\Contracts\Queue\Destination $destination + * @return ConsumerInterface + */ + public function createConsumer(\Phalcon\Contracts\Queue\Destination $destination): ConsumerInterface + { + } + + /** + * @param string $body + * @param array $properties + * @param array $headers + * @return MessageInterface + */ + public function createMessage(string $body = '', array $properties = [], array $headers = []): MessageInterface + { + } + + /** + * @return ProducerInterface + */ + public function createProducer(): ProducerInterface + { + } + + /** + * @return SubscriptionConsumerInterface + */ + public function createSubscriptionConsumer(): SubscriptionConsumerInterface + { + } + + /** + * Default time-to-run (seconds) for new jobs. Used by BeanstalkProducer. + * + * @return int + */ + public function getTtr(): int + { + } + + /** + * @param \Phalcon\Contracts\Queue\Queue $queue + * @return void + */ + public function purgeQueue(\Phalcon\Contracts\Queue\Queue $queue): void + { + } + + /** + * Puts a serialized payload on a tube via the shared connection. + * Internal transport API used by BeanstalkProducer. + * + * @param string $tube + * @param string $payload + * @param int $priority + * @param int $delay + * @param int $ttr + * @return void + */ + public function putMessage(string $tube, string $payload, int $priority, int $delay, int $ttr): void + { + } + + /** + * Returns the shared producer/purge connection, connecting on first use. + * + * @return BeanstalkConnection + */ + private function getConnection(): BeanstalkConnection + { + } + + /** + * Builds and connects a fresh Beanstalkd connection. + * + * @return BeanstalkConnection + */ + private function newConnection(): BeanstalkConnection + { + } +} diff --git a/src/Queue/Adapter/Beanstalk/BeanstalkMessage.php b/src/Queue/Adapter/Beanstalk/BeanstalkMessage.php new file mode 100644 index 00000000..c56b2237 --- /dev/null +++ b/src/Queue/Adapter/Beanstalk/BeanstalkMessage.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Beanstalk; + +use Phalcon\Queue\Adapter\AbstractMessage; + +/** + * Beanstalkd-backed message. Carries the reserved job id so the consumer can + * delete, release, bury or touch it; all other behavior comes from + * AbstractMessage. + */ +class BeanstalkMessage extends AbstractMessage +{ + /** + * The reserved Beanstalkd job id, or null before it is reserved. + * + * @var string | null + */ + protected $jobId = null; + + /** + * @return string|null + */ + public function getJobId(): string|null + { + } + + /** + * @param string $jobId + * @return void + */ + public function setJobId(string $jobId): void + { + } +} diff --git a/src/Queue/Adapter/Beanstalk/BeanstalkProducer.php b/src/Queue/Adapter/Beanstalk/BeanstalkProducer.php new file mode 100644 index 00000000..c5dc7366 --- /dev/null +++ b/src/Queue/Adapter/Beanstalk/BeanstalkProducer.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Beanstalk; + +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Producer as ProducerInterface; +use Phalcon\Queue\Adapter\AbstractProducer; +use Phalcon\Queue\Adapter\MessageEnvelope; +use Phalcon\Queue\Adapter\QueueDestinationGuard; + +/** + * Sends messages to a Beanstalkd tube. Delivery delay (rounded down to whole + * seconds) and message priority are supported natively; Beanstalkd has no + * message expiry, so time to live is not (the default from AbstractProducer + * rejects it). + */ +class BeanstalkProducer extends AbstractProducer +{ + /** + * Default Beanstalkd priority (0 = most urgent). + * + * @var int + */ + const int DEFAULT_PRIORITY = 100; + + /** + * @var BeanstalkContext + */ + protected $context; + + /** + * Delivery delay in milliseconds, or null when not set. + * + * @var int | null + */ + protected $deliveryDelay = null; + + /** + * Job priority, or null when not set. + * + * @var int | null + */ + protected $priority = null; + + /** + * @param BeanstalkContext $context + */ + public function __construct(BeanstalkContext $context) + { + } + + /** + * @return int|null + */ + public function getDeliveryDelay(): int|null + { + } + + /** + * @return int|null + */ + public function getPriority(): int|null + { + } + + /** + * @param \Phalcon\Contracts\Queue\Destination $destination + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function send(\Phalcon\Contracts\Queue\Destination $destination, \Phalcon\Contracts\Queue\Message $message): void + { + } + + /** + * @param mixed $deliveryDelay + * @return ProducerInterface + */ + public function setDeliveryDelay($deliveryDelay = null): ProducerInterface + { + } + + /** + * @param mixed $priority + * @return ProducerInterface + */ + public function setPriority($priority = null): ProducerInterface + { + } +} diff --git a/src/Queue/Adapter/Beanstalk/BeanstalkSubscriptionConsumer.php b/src/Queue/Adapter/Beanstalk/BeanstalkSubscriptionConsumer.php new file mode 100644 index 00000000..dddd8661 --- /dev/null +++ b/src/Queue/Adapter/Beanstalk/BeanstalkSubscriptionConsumer.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Beanstalk; + +use Phalcon\Queue\Adapter\AbstractSubscriptionConsumer; + +/** + * Consumes from several Beanstalkd tubes at once. The round-robin poll loop + * lives in AbstractSubscriptionConsumer. + */ +class BeanstalkSubscriptionConsumer extends AbstractSubscriptionConsumer +{ + /** + * Retained for transports that may later need it for a native multi-queue + * receive; the shared poll loop does not use it. + * + * @var BeanstalkContext + */ + protected $context; + + /** + * @param BeanstalkContext $context + * @param int $pollInterval + */ + public function __construct(BeanstalkContext $context, int $pollInterval = 200) + { + } +} diff --git a/src/Queue/Adapter/GenericQueue.php b/src/Queue/Adapter/GenericQueue.php new file mode 100644 index 00000000..3a346367 --- /dev/null +++ b/src/Queue/Adapter/GenericQueue.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Queue as QueueInterface; + +/** + * A named queue destination shared by every transport. A queue name is the + * only knowledge a destination carries, so the adapters need no transport + * specific subclass. + */ +class GenericQueue implements QueueInterface +{ + /** + * @var string + */ + protected $queueName = ''; + + /** + * GenericQueue constructor. + * + * @param string $queueName + */ + public function __construct(string $queueName) + { + } + + /** + * Returns the queue name. + * + * @return string + */ + public function getQueueName(): string + { + } +} diff --git a/src/Queue/Adapter/GenericTopic.php b/src/Queue/Adapter/GenericTopic.php new file mode 100644 index 00000000..15335782 --- /dev/null +++ b/src/Queue/Adapter/GenericTopic.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Topic as TopicInterface; + +/** + * A named topic destination shared by every transport. A topic name is the + * only knowledge a destination carries, so the adapters need no transport + * specific subclass. + */ +class GenericTopic implements TopicInterface +{ + /** + * @var string + */ + protected $topicName = ''; + + /** + * GenericTopic constructor. + * + * @param string $topicName + */ + public function __construct(string $topicName) + { + } + + /** + * Returns the topic name. + * + * @return string + */ + public function getTopicName(): string + { + } +} diff --git a/src/Queue/Adapter/Memory/MemoryConnectionFactory.php b/src/Queue/Adapter/Memory/MemoryConnectionFactory.php new file mode 100644 index 00000000..b33a1c1a --- /dev/null +++ b/src/Queue/Adapter/Memory/MemoryConnectionFactory.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Memory; + +use Phalcon\Contracts\Queue\ConnectionFactory as ConnectionFactoryInterface; +use Phalcon\Contracts\Queue\Context as ContextInterface; + +/** + * Builds a MemoryContext. The Memory transport takes no options. + */ +class MemoryConnectionFactory implements ConnectionFactoryInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * MemoryConnectionFactory constructor. + * + * @param array $options + */ + public function __construct(array $options = []) + { + } + + /** + * Creates a new in-process context. + * + * @return ContextInterface + */ + public function createContext(): ContextInterface + { + } +} diff --git a/src/Queue/Adapter/Memory/MemoryConsumer.php b/src/Queue/Adapter/Memory/MemoryConsumer.php new file mode 100644 index 00000000..3ac541ee --- /dev/null +++ b/src/Queue/Adapter/Memory/MemoryConsumer.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Memory; + +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Queue\Adapter\AbstractConsumer; + +/** + * Receives messages from a single in-process queue. `receive()` is the + * polling loop inherited from AbstractConsumer. + */ +class MemoryConsumer extends AbstractConsumer +{ + /** + * @var MemoryContext + */ + protected $context; + + /** + * MemoryConsumer constructor. + * + * @param MemoryContext $context + * @param \Phalcon\Contracts\Queue\Queue $queue + */ + public function __construct(MemoryContext $context, \Phalcon\Contracts\Queue\Queue $queue) + { + } + + /** + * No-op: a received message has already been removed from the queue. + * + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function acknowledge(\Phalcon\Contracts\Queue\Message $message): void + { + } + + /** + * Removes and returns the next message, or null when the queue is empty. + * + * @return MessageInterface|null + */ + public function receiveNoWait(): MessageInterface|null + { + } + + /** + * Rejects the message. When requeue is true it is put back on the queue. + * + * @param \Phalcon\Contracts\Queue\Message $message + * @param bool $requeue + * @return void + */ + public function reject(\Phalcon\Contracts\Queue\Message $message, bool $requeue = false): void + { + } +} diff --git a/src/Queue/Adapter/Memory/MemoryContext.php b/src/Queue/Adapter/Memory/MemoryContext.php new file mode 100644 index 00000000..52c5f2d5 --- /dev/null +++ b/src/Queue/Adapter/Memory/MemoryContext.php @@ -0,0 +1,116 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Memory; + +use Phalcon\Contracts\Queue\Consumer as ConsumerInterface; +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Producer as ProducerInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Contracts\Queue\SubscriptionConsumer as SubscriptionConsumerInterface; +use Phalcon\Queue\Adapter\AbstractContext; +use Phalcon\Queue\Adapter\QueueDestinationGuard; + +/** + * In-process transport session. Owns the named FIFO queues that this context's + * producers and consumers share. The destination factories (createQueue / + * createTopic / createTemporaryQueue) come from AbstractContext. + */ +class MemoryContext extends AbstractContext +{ + /** + * Named queues: queue name => list of messages (FIFO). + * + * @var array + */ + protected $queues = []; + + /** + * Closes the context and drops every stored message. + * + * @return void + */ + public function close(): void + { + } + + /** + * Creates a consumer for the given queue destination. + * + * @param \Phalcon\Contracts\Queue\Destination $destination + * @return ConsumerInterface + */ + public function createConsumer(\Phalcon\Contracts\Queue\Destination $destination): ConsumerInterface + { + } + + /** + * Creates a message. + * + * @param string $body + * @param array $properties + * @param array $headers + * @return MessageInterface + */ + public function createMessage(string $body = '', array $properties = [], array $headers = []): MessageInterface + { + } + + /** + * Creates a producer. + * + * @return ProducerInterface + */ + public function createProducer(): ProducerInterface + { + } + + /** + * Creates a subscription consumer. + * + * @return SubscriptionConsumerInterface + */ + public function createSubscriptionConsumer(): SubscriptionConsumerInterface + { + } + + /** + * Removes the front message from a queue, or null when it is empty. + * Internal transport API used by MemoryConsumer. + * + * @param string $queueName + * @return MessageInterface|null + */ + public function popMessage(string $queueName): MessageInterface|null + { + } + + /** + * Removes all messages from the given queue. + * + * @param \Phalcon\Contracts\Queue\Queue $queue + * @return void + */ + public function purgeQueue(\Phalcon\Contracts\Queue\Queue $queue): void + { + } + + /** + * Appends a message to the back of a queue. + * Internal transport API used by MemoryProducer. + * + * @param string $queueName + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function pushMessage(string $queueName, \Phalcon\Contracts\Queue\Message $message): void + { + } +} diff --git a/src/Queue/Adapter/Memory/MemoryMessage.php b/src/Queue/Adapter/Memory/MemoryMessage.php new file mode 100644 index 00000000..3ed69a53 --- /dev/null +++ b/src/Queue/Adapter/Memory/MemoryMessage.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Memory; + +use Phalcon\Queue\Adapter\AbstractMessage; + +/** + * In-process message. All behavior comes from AbstractMessage. + */ +class MemoryMessage extends AbstractMessage +{ +} diff --git a/src/Queue/Adapter/Memory/MemoryProducer.php b/src/Queue/Adapter/Memory/MemoryProducer.php new file mode 100644 index 00000000..54167772 --- /dev/null +++ b/src/Queue/Adapter/Memory/MemoryProducer.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Memory; + +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Queue\Adapter\AbstractProducer; +use Phalcon\Queue\Adapter\QueueDestinationGuard; + +/** + * Sends messages into an in-process queue. The Memory transport delivers + * immediately and in-process, so delivery delay, priority and time to live are + * not supported (the defaults from AbstractProducer reject them). + */ +class MemoryProducer extends AbstractProducer +{ + /** + * @var MemoryContext + */ + protected $context; + + /** + * @param MemoryContext $context + */ + public function __construct(MemoryContext $context) + { + } + + /** + * @param \Phalcon\Contracts\Queue\Destination $destination + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function send(\Phalcon\Contracts\Queue\Destination $destination, \Phalcon\Contracts\Queue\Message $message): void + { + } +} diff --git a/src/Queue/Adapter/Memory/MemorySubscriptionConsumer.php b/src/Queue/Adapter/Memory/MemorySubscriptionConsumer.php new file mode 100644 index 00000000..235eff56 --- /dev/null +++ b/src/Queue/Adapter/Memory/MemorySubscriptionConsumer.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Memory; + +use Phalcon\Queue\Adapter\AbstractSubscriptionConsumer; + +/** + * Consumes from several in-process queues at once. The round-robin poll loop + * lives in AbstractSubscriptionConsumer. + */ +class MemorySubscriptionConsumer extends AbstractSubscriptionConsumer +{ + /** + * Retained for transports that may later need it for a native multi-queue + * receive; the shared poll loop does not use it. + * + * @var MemoryContext + */ + protected $context; + + /** + * @param MemoryContext $context + */ + public function __construct(MemoryContext $context) + { + } +} diff --git a/src/Queue/Adapter/MessageEnvelope.php b/src/Queue/Adapter/MessageEnvelope.php new file mode 100644 index 00000000..f830a30b --- /dev/null +++ b/src/Queue/Adapter/MessageEnvelope.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Message as MessageInterface; + +/** + * Encodes and decodes the {body, properties, headers} envelope shared by every + * transport that persists a message as a serialized string (Stream, Redis, + * Beanstalk). Centralizes the wire shape, the object-injection-safe + * `allowed_classes => false` guard, and the missing-key defaults, so each + * adapter only supplies its own concrete message factory around `decode()`. + */ +class MessageEnvelope +{ + /** + * Decodes a serialized payload into a normalized {body, properties, + * headers} array, or null when the payload is not a valid envelope. + * + * @param string $payload + * @return array|null + */ + public static function decode(string $payload): array|null + { + } + + /** + * Serializes a message into its wire envelope. + * + * @param \Phalcon\Contracts\Queue\Message $message + * @return string + */ + public static function encode(\Phalcon\Contracts\Queue\Message $message): string + { + } +} diff --git a/src/Queue/Adapter/QueueDestinationGuard.php b/src/Queue/Adapter/QueueDestinationGuard.php new file mode 100644 index 00000000..4e94bbfc --- /dev/null +++ b/src/Queue/Adapter/QueueDestinationGuard.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter; + +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Queue\Exceptions\InvalidDestinationException; + +/** + * Shared "destination must be a queue" guard. Producers (on send) and contexts + * (on createConsumer) both reject any non-queue destination with the same typed + * exception; this keeps that single rule in one place. The `action` verb + * ("send to", "consume from") tailors the message to the caller. + */ +class QueueDestinationGuard +{ + /** + * Throws InvalidDestinationException unless the destination is a queue. + * + * @param \Phalcon\Contracts\Queue\Destination $destination + * @param string $action + * @return void + */ + public static function assertQueue(\Phalcon\Contracts\Queue\Destination $destination, string $action): void + { + } +} diff --git a/src/Queue/Adapter/Redis/RedisConnectionFactory.php b/src/Queue/Adapter/Redis/RedisConnectionFactory.php new file mode 100644 index 00000000..0d158f3f --- /dev/null +++ b/src/Queue/Adapter/Redis/RedisConnectionFactory.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Redis; + +use Phalcon\Contracts\Queue\ConnectionFactory as ConnectionFactoryInterface; +use Phalcon\Contracts\Queue\Context as ContextInterface; +use Phalcon\Queue\Exceptions\Exception; +use Phalcon\Storage\Adapter\Redis as StorageRedis; +use Phalcon\Storage\Exception as StorageException; +use Phalcon\Storage\SerializerFactory; + +/** + * Connects to a Redis server (ext-redis) and builds a RedisContext. The + * connection (connect/pconnect, auth, database select) is delegated to + * Phalcon\Storage\Adapter\Redis so the queue reuses the framework's hardened + * connection handling instead of re-implementing it. + * + * Options: + * - host: server host (default 127.0.0.1). + * - port: server port (default 6379). + * - timeout: connection timeout in seconds (default 0). + * - persistent: use a persistent connection (default false). + * - persistentId: identifier for the persistent connection. + * - auth: password, or [user, password] for ACL auth. + * - index: database index to SELECT (default 0). + * - prefix: key prefix for every queue (default "phalcon_queue:"). + * - pollInterval: milliseconds between subscription poll passes (default 200). + */ +class RedisConnectionFactory implements ConnectionFactoryInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * @param array $options + */ + public function __construct(array $options = []) + { + } + + /** + * @return ContextInterface + */ + public function createContext(): ContextInterface + { + } +} diff --git a/src/Queue/Adapter/Redis/RedisConsumer.php b/src/Queue/Adapter/Redis/RedisConsumer.php new file mode 100644 index 00000000..4e37f1b2 --- /dev/null +++ b/src/Queue/Adapter/Redis/RedisConsumer.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Redis; + +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Queue\Adapter\AbstractConsumer; + +/** + * Receives messages from a single Redis queue. `receive()` is overridden to + * use the native blocking BRPOP (in one-second chunks, so due delayed + * messages keep getting promoted) instead of the inherited polling loop. + */ +class RedisConsumer extends AbstractConsumer +{ + /** + * @var RedisContext + */ + protected $context; + + /** + * @param RedisContext $context + * @param \Phalcon\Contracts\Queue\Queue $queue + */ + public function __construct(RedisContext $context, \Phalcon\Contracts\Queue\Queue $queue) + { + } + + /** + * No-op: a received message has already been removed from the queue. + * + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function acknowledge(\Phalcon\Contracts\Queue\Message $message): void + { + } + + /** + * @param int $timeout + * @return MessageInterface|null + */ + public function receive(int $timeout = 0): MessageInterface|null + { + } + + /** + * @return MessageInterface|null + */ + public function receiveNoWait(): MessageInterface|null + { + } + + /** + * @param \Phalcon\Contracts\Queue\Message $message + * @param bool $requeue + * @return void + */ + public function reject(\Phalcon\Contracts\Queue\Message $message, bool $requeue = false): void + { + } +} diff --git a/src/Queue/Adapter/Redis/RedisContext.php b/src/Queue/Adapter/Redis/RedisContext.php new file mode 100644 index 00000000..d3c3ef74 --- /dev/null +++ b/src/Queue/Adapter/Redis/RedisContext.php @@ -0,0 +1,189 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Redis; + +use Phalcon\Contracts\Queue\Consumer as ConsumerInterface; +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Producer as ProducerInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Contracts\Queue\SubscriptionConsumer as SubscriptionConsumerInterface; +use Phalcon\Queue\Adapter\AbstractContext; +use Phalcon\Queue\Adapter\MessageEnvelope; +use Phalcon\Queue\Adapter\QueueDestinationGuard; + +/** + * Redis transport session (ext-redis). Each queue is a Redis list; messages + * are LPUSHed on send and RPOP/BRPOPed on receive, giving FIFO delivery. + * Delayed messages live in a companion sorted set (`:delayed`) scored by + * their due time in milliseconds, and are promoted into the list once due. The + * destination factories come from AbstractContext. + */ +class RedisContext extends AbstractContext +{ + /** + * Milliseconds slept between poll passes by a subscription consumer. + * + * @var int + */ + protected $pollInterval = 200; + + /** + * Key prefix applied to every queue (and its delayed companion set). + * + * @var string + */ + protected $prefix = 'phalcon_queue:'; + + /** + * The connected ext-redis client. + * + * @var \Redis + */ + protected $redis; + + /** + * @param mixed $redis + * @param string $prefix + * @param int $pollInterval + */ + public function __construct($redis, string $prefix = 'phalcon_queue:', int $pollInterval = 200) + { + } + + /** + * Blocking pop from the back of a queue list. Promotes any due delayed + * messages first, then blocks up to timeout seconds. Internal transport + * API used by RedisConsumer. + * + * @param string $queueName + * @param int $timeout + * @return MessageInterface|null + */ + public function blockingPop(string $queueName, int $timeout): MessageInterface|null + { + } + + /** + * @return void + */ + public function close(): void + { + } + + /** + * @param \Phalcon\Contracts\Queue\Destination $destination + * @return ConsumerInterface + */ + public function createConsumer(\Phalcon\Contracts\Queue\Destination $destination): ConsumerInterface + { + } + + /** + * @param string $body + * @param array $properties + * @param array $headers + * @return MessageInterface + */ + public function createMessage(string $body = '', array $properties = [], array $headers = []): MessageInterface + { + } + + /** + * @return ProducerInterface + */ + public function createProducer(): ProducerInterface + { + } + + /** + * @return SubscriptionConsumerInterface + */ + public function createSubscriptionConsumer(): SubscriptionConsumerInterface + { + } + + /** + * Non-blocking pop from the back of a queue list, or null when empty. + * Promotes any due delayed messages first. Internal transport API used + * by RedisConsumer. + * + * @param string $queueName + * @return MessageInterface|null + */ + public function popMessage(string $queueName): MessageInterface|null + { + } + + /** + * @param \Phalcon\Contracts\Queue\Queue $queue + * @return void + */ + public function purgeQueue(\Phalcon\Contracts\Queue\Queue $queue): void + { + } + + /** + * Sends a message to a queue. With a positive delay (milliseconds) the + * message is parked in the delayed set; otherwise it is pushed onto the + * front of the list. Internal transport API used by RedisProducer. + * + * @param string $queueName + * @param \Phalcon\Contracts\Queue\Message $message + * @param int $delay + * @return void + */ + public function pushMessage(string $queueName, \Phalcon\Contracts\Queue\Message $message, int $delay = 0): void + { + } + + /** + * @param string $payload + * @return MessageInterface|null + */ + private function buildMessage(string $payload): MessageInterface|null + { + } + + /** + * @param string $queueName + * @return string + */ + private function delayedKey(string $queueName): string + { + } + + /** + * @param string $queueName + * @return string + */ + private function listKey(string $queueName): string + { + } + + /** + * @return int + */ + private function now(): int + { + } + + /** + * Moves every due message from the delayed set onto the queue list. The + * ZREM acts as an atomic claim, so a message promoted by one process is + * never promoted again by another. + * + * @param string $queueName + * @return void + */ + private function promote(string $queueName): void + { + } +} diff --git a/src/Queue/Adapter/Redis/RedisMessage.php b/src/Queue/Adapter/Redis/RedisMessage.php new file mode 100644 index 00000000..5e14ecef --- /dev/null +++ b/src/Queue/Adapter/Redis/RedisMessage.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Redis; + +use Phalcon\Queue\Adapter\AbstractMessage; + +/** + * Redis-backed message. All behavior comes from AbstractMessage. + */ +class RedisMessage extends AbstractMessage +{ +} diff --git a/src/Queue/Adapter/Redis/RedisProducer.php b/src/Queue/Adapter/Redis/RedisProducer.php new file mode 100644 index 00000000..9b6dfc54 --- /dev/null +++ b/src/Queue/Adapter/Redis/RedisProducer.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Redis; + +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Producer as ProducerInterface; +use Phalcon\Queue\Adapter\AbstractProducer; +use Phalcon\Queue\Adapter\QueueDestinationGuard; + +/** + * Sends messages to a Redis queue. Delivery delay is supported (via the + * delayed sorted set); priority and time to live are not (the defaults from + * AbstractProducer reject them). + */ +class RedisProducer extends AbstractProducer +{ + /** + * @var RedisContext + */ + protected $context; + + /** + * Delivery delay in milliseconds, or null when not set. + * + * @var int | null + */ + protected $deliveryDelay = null; + + /** + * @param RedisContext $context + */ + public function __construct(RedisContext $context) + { + } + + /** + * @return int|null + */ + public function getDeliveryDelay(): int|null + { + } + + /** + * @param \Phalcon\Contracts\Queue\Destination $destination + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function send(\Phalcon\Contracts\Queue\Destination $destination, \Phalcon\Contracts\Queue\Message $message): void + { + } + + /** + * @param mixed $deliveryDelay + * @return ProducerInterface + */ + public function setDeliveryDelay($deliveryDelay = null): ProducerInterface + { + } +} diff --git a/src/Queue/Adapter/Redis/RedisSubscriptionConsumer.php b/src/Queue/Adapter/Redis/RedisSubscriptionConsumer.php new file mode 100644 index 00000000..b5067322 --- /dev/null +++ b/src/Queue/Adapter/Redis/RedisSubscriptionConsumer.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Redis; + +use Phalcon\Queue\Adapter\AbstractSubscriptionConsumer; + +/** + * Consumes from several Redis queues at once. The round-robin poll loop lives + * in AbstractSubscriptionConsumer. + */ +class RedisSubscriptionConsumer extends AbstractSubscriptionConsumer +{ + /** + * Retained for transports that may later need it for a native multi-queue + * receive; the shared poll loop does not use it. + * + * @var RedisContext + */ + protected $context; + + /** + * @param RedisContext $context + * @param int $pollInterval + */ + public function __construct(RedisContext $context, int $pollInterval = 200) + { + } +} diff --git a/src/Queue/Adapter/Stream/StreamConnectionFactory.php b/src/Queue/Adapter/Stream/StreamConnectionFactory.php new file mode 100644 index 00000000..e7f62ae5 --- /dev/null +++ b/src/Queue/Adapter/Stream/StreamConnectionFactory.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Stream; + +use Phalcon\Contracts\Queue\ConnectionFactory as ConnectionFactoryInterface; +use Phalcon\Contracts\Queue\Context as ContextInterface; + +/** + * Builds a StreamContext. + * + * Options: + * - storageDir: directory holding the queue files (default: system temp). + * - pollInterval: milliseconds between consumer poll attempts (default 200). + */ +class StreamConnectionFactory implements ConnectionFactoryInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * @param array $options + */ + public function __construct(array $options = []) + { + } + + /** + * @return ContextInterface + */ + public function createContext(): ContextInterface + { + } +} diff --git a/src/Queue/Adapter/Stream/StreamConsumer.php b/src/Queue/Adapter/Stream/StreamConsumer.php new file mode 100644 index 00000000..c9eaf05c --- /dev/null +++ b/src/Queue/Adapter/Stream/StreamConsumer.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Stream; + +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Queue\Adapter\AbstractConsumer; + +/** + * Receives messages from a single filesystem queue. `receive()` is the + * polling loop inherited from AbstractConsumer. + */ +class StreamConsumer extends AbstractConsumer +{ + /** + * @var StreamContext + */ + protected $context; + + /** + * @param StreamContext $context + * @param \Phalcon\Contracts\Queue\Queue $queue + * @param int $pollInterval + */ + public function __construct(StreamContext $context, \Phalcon\Contracts\Queue\Queue $queue, int $pollInterval = 200) + { + } + + /** + * No-op: a received message has already been removed from the queue file. + * + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function acknowledge(\Phalcon\Contracts\Queue\Message $message): void + { + } + + /** + * @return MessageInterface|null + */ + public function receiveNoWait(): MessageInterface|null + { + } + + /** + * @param \Phalcon\Contracts\Queue\Message $message + * @param bool $requeue + * @return void + */ + public function reject(\Phalcon\Contracts\Queue\Message $message, bool $requeue = false): void + { + } +} diff --git a/src/Queue/Adapter/Stream/StreamContext.php b/src/Queue/Adapter/Stream/StreamContext.php new file mode 100644 index 00000000..c69ffaca --- /dev/null +++ b/src/Queue/Adapter/Stream/StreamContext.php @@ -0,0 +1,136 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Stream; + +use Phalcon\Contracts\Queue\Consumer as ConsumerInterface; +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Producer as ProducerInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Contracts\Queue\SubscriptionConsumer as SubscriptionConsumerInterface; +use Phalcon\Queue\Adapter\AbstractContext; +use Phalcon\Queue\Adapter\MessageEnvelope; +use Phalcon\Queue\Adapter\QueueDestinationGuard; + +/** + * Filesystem transport session. Each queue is one append-only file under the + * configured directory; cross-process safety comes from flock. One message + * per line, stored as base64(serialize([...])) so bodies with newlines are + * safe. The destination factories come from AbstractContext. + */ +class StreamContext extends AbstractContext +{ + /** + * Milliseconds slept between poll attempts by consumers. + * + * @var int + */ + protected $pollInterval = 200; + + /** + * Directory (with trailing separator) that holds the queue files. + * + * @var string + */ + protected $storageDir = ''; + + /** + * @param string $storageDir + * @param int $pollInterval + */ + public function __construct(string $storageDir, int $pollInterval = 200) + { + } + + /** + * @return void + */ + public function close(): void + { + } + + /** + * @param \Phalcon\Contracts\Queue\Destination $destination + * @return ConsumerInterface + */ + public function createConsumer(\Phalcon\Contracts\Queue\Destination $destination): ConsumerInterface + { + } + + /** + * @param string $body + * @param array $properties + * @param array $headers + * @return MessageInterface + */ + public function createMessage(string $body = '', array $properties = [], array $headers = []): MessageInterface + { + } + + /** + * @return ProducerInterface + */ + public function createProducer(): ProducerInterface + { + } + + /** + * @return SubscriptionConsumerInterface + */ + public function createSubscriptionConsumer(): SubscriptionConsumerInterface + { + } + + /** + * Removes the front message from a queue file, or null when it is empty. + * Internal transport API used by StreamConsumer. + * + * @param string $queueName + * @return MessageInterface|null + */ + public function popMessage(string $queueName): MessageInterface|null + { + } + + /** + * @param \Phalcon\Contracts\Queue\Queue $queue + * @return void + */ + public function purgeQueue(\Phalcon\Contracts\Queue\Queue $queue): void + { + } + + /** + * Appends a message to the back of a queue file. + * Internal transport API used by StreamProducer. + * + * @param string $queueName + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function pushMessage(string $queueName, \Phalcon\Contracts\Queue\Message $message): void + { + } + + /** + * @return void + */ + private function ensureDir(): void + { + } + + /** + * @param string $queueName + * @return string + */ + private function getFilepath(string $queueName): string + { + } +} diff --git a/src/Queue/Adapter/Stream/StreamMessage.php b/src/Queue/Adapter/Stream/StreamMessage.php new file mode 100644 index 00000000..e7f3f4e1 --- /dev/null +++ b/src/Queue/Adapter/Stream/StreamMessage.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Stream; + +use Phalcon\Queue\Adapter\AbstractMessage; + +/** + * Filesystem-backed message. All behavior comes from AbstractMessage. + */ +class StreamMessage extends AbstractMessage +{ +} diff --git a/src/Queue/Adapter/Stream/StreamProducer.php b/src/Queue/Adapter/Stream/StreamProducer.php new file mode 100644 index 00000000..227317ed --- /dev/null +++ b/src/Queue/Adapter/Stream/StreamProducer.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Stream; + +use Phalcon\Contracts\Queue\Destination as DestinationInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Queue\Adapter\AbstractProducer; +use Phalcon\Queue\Adapter\QueueDestinationGuard; + +/** + * Appends messages to a filesystem queue. The Stream transport delivers in + * insertion order with no scheduling, so delivery delay, priority and time to + * live are not supported (the defaults from AbstractProducer reject them). + */ +class StreamProducer extends AbstractProducer +{ + /** + * @var StreamContext + */ + protected $context; + + /** + * @param StreamContext $context + */ + public function __construct(StreamContext $context) + { + } + + /** + * @param \Phalcon\Contracts\Queue\Destination $destination + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + public function send(\Phalcon\Contracts\Queue\Destination $destination, \Phalcon\Contracts\Queue\Message $message): void + { + } +} diff --git a/src/Queue/Adapter/Stream/StreamSubscriptionConsumer.php b/src/Queue/Adapter/Stream/StreamSubscriptionConsumer.php new file mode 100644 index 00000000..68715ff1 --- /dev/null +++ b/src/Queue/Adapter/Stream/StreamSubscriptionConsumer.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Adapter\Stream; + +use Phalcon\Queue\Adapter\AbstractSubscriptionConsumer; + +/** + * Consumes from several filesystem queues at once. The round-robin poll loop + * lives in AbstractSubscriptionConsumer. + */ +class StreamSubscriptionConsumer extends AbstractSubscriptionConsumer +{ + /** + * Retained for transports that may later need it for a native multi-queue + * receive; the shared poll loop does not use it. + * + * @var StreamContext + */ + protected $context; + + /** + * @param StreamContext $context + * @param int $pollInterval + */ + public function __construct(StreamContext $context, int $pollInterval = 200) + { + } +} diff --git a/src/Queue/AdapterFactory.php b/src/Queue/AdapterFactory.php new file mode 100644 index 00000000..7417e26c --- /dev/null +++ b/src/Queue/AdapterFactory.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue; + +use Phalcon\Contracts\Queue\ConnectionFactory as ConnectionFactoryInterface; +use Phalcon\Factory\AbstractFactory; + +/** + * Maps an adapter name to its ConnectionFactory. Mirrors + * Phalcon\Storage\AdapterFactory. + */ +class AdapterFactory extends AbstractFactory +{ + /** + * AdapterFactory constructor. + * + * @param array $services + */ + public function __construct(array $services = []) + { + } + + /** + * Creates a new ConnectionFactory for the named adapter. + * + * @param string $name + * @param array $options + * @return ConnectionFactoryInterface + */ + public function newInstance(string $name, array $options = []): ConnectionFactoryInterface + { + } + + /** + * @return string + */ + protected function getExceptionClass(): string + { + } + + /** + * Returns the available adapters. + * + * @return string[] + */ + protected function getServices(): array + { + } +} diff --git a/src/Queue/Cli/ConsumerTask.php b/src/Queue/Cli/ConsumerTask.php new file mode 100644 index 00000000..30ddc487 --- /dev/null +++ b/src/Queue/Cli/ConsumerTask.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Cli; + +use Phalcon\Di\DiInterface; +use Phalcon\Cli\Task; +use Phalcon\Queue\Consumer\QueueConsumer; +use Phalcon\Queue\Consumer\Worker; +use Phalcon\Queue\Consumer\WorkerOptions; + +/** + * Optional CLI runner for a queue worker - the only class coupled to + * Phalcon\Cli. A thin adapter: it resolves the context from the `queueFactory` + * service, binds one queue to one processor (both given as command arguments), + * and runs a Worker whose lifetime bounds come from CLI options. Users not on + * Phalcon\Cli use Worker directly. + * + * Usage: + * \ + * [--max-messages=N] [--max-time=SECONDS] \ + * [--max-memory=MB] [--jitter=SECONDS] + * + * Register it in your own Phalcon\Cli\Console; it is not auto-wired into + * FactoryDefault. + */ +class ConsumerTask extends Task +{ + /** + * @return int + */ + public function mainAction(): int + { + } +} diff --git a/src/Queue/Consumer/BoundProcessor.php b/src/Queue/Consumer/BoundProcessor.php new file mode 100644 index 00000000..ac480922 --- /dev/null +++ b/src/Queue/Consumer/BoundProcessor.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Consumer; + +use Phalcon\Contracts\Queue\Consumer as ConsumerInterface; +use Phalcon\Contracts\Queue\Processor as ProcessorInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; + +/** + * Binds a processor to a queue, together with the consumer that reads it. + */ +class BoundProcessor +{ + /** + * @var ConsumerInterface + */ + protected $consumer; + + /** + * @var ProcessorInterface + */ + protected $processor; + + /** + * @var QueueInterface + */ + protected $queue; + + /** + * @param \Phalcon\Contracts\Queue\Queue $queue + * @param \Phalcon\Contracts\Queue\Processor $processor + * @param \Phalcon\Contracts\Queue\Consumer $consumer + */ + public function __construct(\Phalcon\Contracts\Queue\Queue $queue, \Phalcon\Contracts\Queue\Processor $processor, \Phalcon\Contracts\Queue\Consumer $consumer) + { + } + + /** + * @return ConsumerInterface + */ + public function getConsumer(): ConsumerInterface + { + } + + /** + * @return ProcessorInterface + */ + public function getProcessor(): ProcessorInterface + { + } + + /** + * @return QueueInterface + */ + public function getQueue(): QueueInterface + { + } +} diff --git a/src/Queue/Consumer/Events.php b/src/Queue/Consumer/Events.php new file mode 100644 index 00000000..97bea2a8 --- /dev/null +++ b/src/Queue/Consumer/Events.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Consumer; + +/** + * Lifecycle event names fired by the queue consumer through + * Phalcon\Events\Manager. One public constant per event. + */ +class Events +{ + /** + * @var string + */ + const string AFTER_END = 'queue:afterEnd'; + + /** + * @var string + */ + const string AFTER_PROCESS = 'queue:afterProcess'; + + /** + * @var string + */ + const string AFTER_RECEIVE = 'queue:afterReceive'; + + /** + * @var string + */ + const string BEFORE_PROCESS = 'queue:beforeProcess'; + + /** + * @var string + */ + const string BEFORE_RECEIVE = 'queue:beforeReceive'; + + /** + * @var string + */ + const string BEFORE_START = 'queue:beforeStart'; + + /** + * @var string + */ + const string PROCESSOR_EXCEPTION = 'queue:processorException'; +} diff --git a/src/Queue/Consumer/QueueConsumer.php b/src/Queue/Consumer/QueueConsumer.php new file mode 100644 index 00000000..17587a68 --- /dev/null +++ b/src/Queue/Consumer/QueueConsumer.php @@ -0,0 +1,165 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Consumer; + +use Phalcon\Contracts\Queue\Context as ContextInterface; +use Phalcon\Contracts\Queue\Message as MessageInterface; +use Phalcon\Contracts\Queue\Processor as ProcessorInterface; +use Phalcon\Contracts\Queue\Queue as QueueInterface; +use Phalcon\Events\AbstractEventsAware; +use Phalcon\Events\EventsAwareInterface; + +/** + * Lean consumption runner. Binds processors to queues, polls each bound queue + * round-robin, and dispatches messages to their processors while firing the + * lifecycle events on `Phalcon\Queue\Consumer\Events` through the events + * manager. The long-running operational shell (lifetime, signals) lives in + * `Phalcon\Queue\Consumer\Worker`, which drives `consumeOnce()` and shares the + * stop signal through `stop()` / `isStopRequested()`. + */ +class QueueConsumer extends AbstractEventsAware implements \Phalcon\Events\EventsAwareInterface +{ + /** + * Bound processors keyed by queue name. + * + * @var array + */ + protected $bindings = []; + + /** + * @var ContextInterface + */ + protected $context; + + /** + * Milliseconds slept between poll passes when nothing was received. + * + * @var int + */ + protected $pollInterval = 200; + + /** + * @var bool + */ + protected $shouldStop = false; + + /** + * @param \Phalcon\Contracts\Queue\Context $context + */ + public function __construct(\Phalcon\Contracts\Queue\Context $context) + { + } + + /** + * Binds a processor to a queue. Returns self for chaining. + * + * @param \Phalcon\Contracts\Queue\Queue $queue + * @param \Phalcon\Contracts\Queue\Processor $processor + * @return QueueConsumer + */ + public function bind(\Phalcon\Contracts\Queue\Queue $queue, \Phalcon\Contracts\Queue\Processor $processor): QueueConsumer + { + } + + /** + * Runs the consumption loop, blocking up to timeout milliseconds (0 = + * block until stopped). The simple loop; production setups use Worker. + * + * @param int $timeout + * @return void + */ + public function consume(int $timeout = 0): void + { + } + + /** + * Polls every bound queue once, processing up to one message from each. + * Returns true if any message was handled. Sleeps the poll interval when + * nothing was received so callers can loop tightly. + * + * @return bool + */ + public function consumeOnce(): bool + { + } + + /** + * Fires the `queue:afterEnd` event. Called once the loop exits. + * + * @return void + */ + public function end(): void + { + } + + /** + * Whether a stop has been requested (by a signal, `stop()`, or an + * `afterReceive` listener returning false). + * + * @return bool + */ + public function isStopRequested(): bool + { + } + + /** + * Sets the poll interval (in milliseconds). + * + * @param int $pollInterval + * @return void + */ + public function setPollInterval(int $pollInterval): void + { + } + + /** + * Resets the stop flag and fires `queue:beforeStart`. Returns false when a + * listener cancels the start. + * + * @return bool + */ + public function start(): bool + { + } + + /** + * Requests the consumption loop to stop after the current message. + * + * @return void + */ + public function stop(): void + { + } + + /** + * Applies a processor result (ACK / REJECT / REQUEUE) to the message. + * + * @param mixed $consumer + * @param \Phalcon\Contracts\Queue\Message $message + * @param mixed $result + * @return void + */ + private function handleResult($consumer, \Phalcon\Contracts\Queue\Message $message, $result): void + { + } + + /** + * Runs the processor for one message, firing the process events and + * applying the outcome. A processor exception fires + * `queue:processorException` and rejects the message. + * + * @param mixed $binding + * @param \Phalcon\Contracts\Queue\Message $message + * @return void + */ + private function process($binding, \Phalcon\Contracts\Queue\Message $message): void + { + } +} diff --git a/src/Queue/Consumer/Worker.php b/src/Queue/Consumer/Worker.php new file mode 100644 index 00000000..a4f92712 --- /dev/null +++ b/src/Queue/Consumer/Worker.php @@ -0,0 +1,68 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Consumer; + +/** + * Long-running operational shell around a QueueConsumer. Owns the outer loop, + * the bounded lifetime (max messages / seconds / memory, plus jitter) and - + * when ext-pcntl is available - graceful shutdown on SIGTERM/SIGINT/SIGQUIT. + * The current message always finishes before the loop stops (drain, not + * guillotine), because the stop flag is only checked between iterations. + */ +class Worker +{ + /** + * @var QueueConsumer + */ + protected $consumer; + + /** + * @var WorkerOptions + */ + protected $options; + + /** + * @param QueueConsumer $consumer + * @param WorkerOptions|null $options + */ + public function __construct(QueueConsumer $consumer, ?WorkerOptions $options = null) + { + } + + /** + * Signal handler: requests a graceful stop. + * + * @param int $signal + * @return void + */ + public function handleSignal(int $signal): void + { + } + + /** + * Runs the worker until a lifetime bound trips or a stop is requested. + * Returns the number of messages processed. + * + * @return int + */ + public function run(): int + { + } + + /** + * Installs graceful-shutdown signal handlers when ext-pcntl is available; + * a no-op otherwise (the lifetime bounds still apply). + * + * @return void + */ + private function installSignalHandlers(): void + { + } +} diff --git a/src/Queue/Consumer/WorkerOptions.php b/src/Queue/Consumer/WorkerOptions.php new file mode 100644 index 00000000..7489e22e --- /dev/null +++ b/src/Queue/Consumer/WorkerOptions.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Consumer; + +/** + * Immutable lifetime bounds for a Worker. A value of 0 means "no limit". + * The worker stops on whichever bound trips first. + */ +class WorkerOptions +{ + /** + * Seconds added to maxSeconds (randomised per worker) so a pool does not + * restart in lockstep. + * + * @var int + */ + protected $jitter = 0; + + /** + * Memory ceiling in megabytes. + * + * @var int + */ + protected $maxMemory = 0; + + /** + * Maximum number of messages to process. + * + * @var int + */ + protected $maxMessages = 0; + + /** + * Maximum run time in seconds. + * + * @var int + */ + protected $maxSeconds = 0; + + /** + * @param int $maxMessages + * @param int $maxSeconds + * @param int $maxMemory + * @param int $jitter + */ + public function __construct(int $maxMessages = 0, int $maxSeconds = 0, int $maxMemory = 0, int $jitter = 0) + { + } + + /** + * @return int + */ + public function getJitter(): int + { + } + + /** + * @return int + */ + public function getMaxMemory(): int + { + } + + /** + * @return int + */ + public function getMaxMessages(): int + { + } + + /** + * @return int + */ + public function getMaxSeconds(): int + { + } +} diff --git a/src/Queue/Exceptions/DeliveryDelayNotSupportedException.php b/src/Queue/Exceptions/DeliveryDelayNotSupportedException.php new file mode 100644 index 00000000..9211a8d0 --- /dev/null +++ b/src/Queue/Exceptions/DeliveryDelayNotSupportedException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Thrown when the transport does not support a delivery delay. + */ +class DeliveryDelayNotSupportedException extends \Phalcon\Queue\Exceptions\Exception +{ + public function __construct() + { + } +} diff --git a/src/Queue/Exceptions/Exception.php b/src/Queue/Exceptions/Exception.php new file mode 100644 index 00000000..f1be13d6 --- /dev/null +++ b/src/Queue/Exceptions/Exception.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +use Exception as BaseException; + +/** + * Generic exception for the Queue component, and the base for every typed + * queue exception. + */ +class Exception extends \Exception implements \Phalcon\Queue\Exceptions\QueueThrowable +{ +} diff --git a/src/Queue/Exceptions/InvalidDestinationException.php b/src/Queue/Exceptions/InvalidDestinationException.php new file mode 100644 index 00000000..76b4aeba --- /dev/null +++ b/src/Queue/Exceptions/InvalidDestinationException.php @@ -0,0 +1,25 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Thrown when a destination is not valid for the operation, for example a + * Topic passed where a Queue is required. The action verb ("send to", + * "consume from") tailors the message to the failing operation. + */ +class InvalidDestinationException extends \Phalcon\Queue\Exceptions\Exception +{ + /** + * @param string $action + */ + public function __construct(string $action) + { + } +} diff --git a/src/Queue/Exceptions/InvalidMessageException.php b/src/Queue/Exceptions/InvalidMessageException.php new file mode 100644 index 00000000..5c955333 --- /dev/null +++ b/src/Queue/Exceptions/InvalidMessageException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Thrown when a message is not valid for the operation. + */ +class InvalidMessageException extends \Phalcon\Queue\Exceptions\Exception +{ + public function __construct() + { + } +} diff --git a/src/Queue/Exceptions/PriorityNotSupportedException.php b/src/Queue/Exceptions/PriorityNotSupportedException.php new file mode 100644 index 00000000..856c476a --- /dev/null +++ b/src/Queue/Exceptions/PriorityNotSupportedException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Thrown when the transport does not support message priority. + */ +class PriorityNotSupportedException extends \Phalcon\Queue\Exceptions\Exception +{ + public function __construct() + { + } +} diff --git a/src/Queue/Exceptions/PurgeQueueNotSupportedException.php b/src/Queue/Exceptions/PurgeQueueNotSupportedException.php new file mode 100644 index 00000000..4ac8f9ea --- /dev/null +++ b/src/Queue/Exceptions/PurgeQueueNotSupportedException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Thrown when the transport does not support purging a queue. + */ +class PurgeQueueNotSupportedException extends \Phalcon\Queue\Exceptions\Exception +{ + public function __construct() + { + } +} diff --git a/src/Queue/Exceptions/QueueThrowable.php b/src/Queue/Exceptions/QueueThrowable.php new file mode 100644 index 00000000..5b791926 --- /dev/null +++ b/src/Queue/Exceptions/QueueThrowable.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Base throwable contract for the Queue component. Every queue exception + * implements it, so callers can catch all queue errors with a single type. + */ +interface QueueThrowable extends \Throwable +{ +} diff --git a/src/Queue/Exceptions/SubscriptionConsumerNotSupportedException.php b/src/Queue/Exceptions/SubscriptionConsumerNotSupportedException.php new file mode 100644 index 00000000..8af34968 --- /dev/null +++ b/src/Queue/Exceptions/SubscriptionConsumerNotSupportedException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Thrown when the transport does not support subscription consumers. + */ +class SubscriptionConsumerNotSupportedException extends \Phalcon\Queue\Exceptions\Exception +{ + public function __construct() + { + } +} diff --git a/src/Queue/Exceptions/TemporaryQueueNotSupportedException.php b/src/Queue/Exceptions/TemporaryQueueNotSupportedException.php new file mode 100644 index 00000000..19e83f43 --- /dev/null +++ b/src/Queue/Exceptions/TemporaryQueueNotSupportedException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Thrown when the transport does not support temporary queues. + */ +class TemporaryQueueNotSupportedException extends \Phalcon\Queue\Exceptions\Exception +{ + public function __construct() + { + } +} diff --git a/src/Queue/Exceptions/TimeToLiveNotSupportedException.php b/src/Queue/Exceptions/TimeToLiveNotSupportedException.php new file mode 100644 index 00000000..b910643b --- /dev/null +++ b/src/Queue/Exceptions/TimeToLiveNotSupportedException.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue\Exceptions; + +/** + * Thrown when the transport does not support a message time to live. + */ +class TimeToLiveNotSupportedException extends \Phalcon\Queue\Exceptions\Exception +{ + public function __construct() + { + } +} diff --git a/src/Queue/QueueFactory.php b/src/Queue/QueueFactory.php new file mode 100644 index 00000000..4d0cae2c --- /dev/null +++ b/src/Queue/QueueFactory.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Queue; + +use Phalcon\Contracts\Queue\Context as ContextInterface; +use Phalcon\Factory\AbstractConfigFactory; + +/** + * Builds a queue Context from the standard Phalcon config shape. Mirrors + * Phalcon\Cache\CacheFactory. + */ +class QueueFactory extends AbstractConfigFactory +{ + /** + * @var AdapterFactory + */ + protected $adapterFactory; + + /** + * QueueFactory constructor. A default AdapterFactory is created when none + * is supplied, so the factory is usable straight from the DI container. + * + * @param AdapterFactory|null $factory + */ + public function __construct(?AdapterFactory $factory = null) + { + } + + /** + * Builds a Context from a config array/object. + * + * @param array $config = [ + * 'adapter' => 'memory', + * 'options' => [] + * ] + * @return ContextInterface + */ + public function load($config): ContextInterface + { + } + + /** + * Builds a Context for the named adapter. + * + * @param string $name + * @param array $options + * @return ContextInterface + */ + public function newInstance(string $name, array $options = []): ContextInterface + { + } + + /** + * @return string + */ + protected function getExceptionClass(): string + { + } +} diff --git a/src/Support/Debug.php b/src/Support/Debug.php index 089522ff..01a68c50 100644 --- a/src/Support/Debug.php +++ b/src/Support/Debug.php @@ -9,15 +9,18 @@ */ namespace Phalcon\Support; +use Phalcon\Contracts\Support\Debug\Renderer; use Phalcon\Support\Debug\Exceptions\RequestHalted; use Phalcon\Support\Debug\Exceptions\RuntimeWarning; -use ReflectionClass; +use Phalcon\Support\Debug\Renderer\HtmlRenderer; +use Phalcon\Support\Debug\ReportBuilder; +use Phalcon\Support\Helper\Arr\Get; use ReflectionException; -use ReflectionFunction; use Throwable; /** - * Provides debug capabilities to Phalcon applications + * Listens for uncaught exceptions and renders them. Acts as a thin coordinator + * delegating data collection to ReportBuilder and presentation to a Renderer. */ class Debug { @@ -41,6 +44,16 @@ class Debug */ protected static $isActive = false; + /** + * @var Renderer + */ + protected $renderer; + + /** + * @var ReportBuilder + */ + protected $reportBuilder; + /** * @var bool */ @@ -61,6 +74,10 @@ class Debug */ protected $uri = 'https://assets.phalcon.io/debug/5.0.x/'; + public function __construct() + { + } + /** * Clears are variables added previously * @@ -99,6 +116,15 @@ public function getJsSources(): string { } + /** + * Returns the renderer used to produce the output + * + * @return Renderer + */ + public function getRenderer(): Renderer + { + } + /** * Generates a link to the current version documentation * @@ -150,6 +176,7 @@ public function listenLowSeverity(): static /** * Handles uncaught exceptions * + * @throws ReflectionException * @param \Throwable $exception * @return bool */ @@ -192,6 +219,16 @@ public function setBlacklist(array $blacklist): static { } + /** + * Sets the renderer used to produce the output + * + * @param Renderer $renderer + * @return static + */ + public function setRenderer(\Phalcon\Contracts\Support\Debug\Renderer $renderer): static + { + } + /** * Sets if files the exception's backtrace must be showed * @@ -232,122 +269,4 @@ public function setShowFiles(bool $showFiles): static public function setUri(string $uri): static { } - - /** - * Escapes a string with htmlentities - * - * @param string $value - * @return string - */ - protected function escapeString(string $value): string - { - } - - /** - * Produces a recursive representation of an array - * - * @param array $arguments - * @param int $number - * - * @return string|null - * @param array $argument - * @param mixed $n - */ - protected function getArrayDump(array $argument, $n = 0): string|null - { - } - - /** - * Produces an string representation of a variable - * - * @param mixed $variable - * @return string - */ - protected function getVarDump($variable): string - { - } - - /** - * Shows a backtrace item - * - * @param int $number - * @param array $trace - * - * @return string - * @throws ReflectionException - */ - final protected function showTraceItem(int $number, array $trace): string - { - } - - /** - * @return string - */ - private function closeTable(): string - { - } - - /** - * @param Throwable $exception - * - * @return string - * @throws ReflectionException - */ - private function printBacktrace(\Throwable $exception): string - { - } - - /** - * @return string - */ - private function printExtraVariables(): string - { - } - - /** - * @return string - */ - private function printIncludedFiles(): string - { - } - - /** - * @return string - */ - private function printMemoryUsage(): string - { - } - - /** - * @param array $source - * @param string $div - * - * @return string - */ - private function printSuperglobal(array $source, string $div): string - { - } - - /** - * @param string $divId - * @param string $headerOne - * @param string $headerTwo - * @param string $colspan - * - * @return string - */ - private function printTableHeader(string $divId, string $headerOne, string $headerTwo, string $colspan = ''): string - { - } - - /** - * @todo Remove this when we get traits - * @param array $collection - * @param mixed $index - * @param mixed $defaultValue - * @return mixed - */ - private function getArrVal(array $collection, $index, $defaultValue = null): mixed - { - } } diff --git a/src/Support/Debug/Dump.php b/src/Support/Debug/Dump.php index fcc81f31..183faed7 100644 --- a/src/Support/Debug/Dump.php +++ b/src/Support/Debug/Dump.php @@ -9,6 +9,7 @@ */ namespace Phalcon\Support\Debug; +use Phalcon\Contracts\Support\Debug\TemplateAware; use Phalcon\Di\DiInterface; use Phalcon\Support\Helper\Json\Encode; use Reflection; @@ -33,7 +34,7 @@ * echo (new \Phalcon\Debug\Dump())->variables($foo, $bar, $baz); * ``` */ -class Dump +class Dump implements \Phalcon\Contracts\Support\Debug\TemplateAware { /** * @var bool @@ -50,6 +51,17 @@ class Dump */ protected $styles = []; + /** + * Template overrides keyed by name. + * + * @todo Move getTemplate()/setTemplate()/templates into a shared trait once + * Zephir supports traits (mirrors + * Phalcon\Support\Debug\Traits\TemplateAwareTrait in the PHP source). + * + * @var array + */ + protected $templates = []; + /** * @var Encode */ @@ -81,6 +93,18 @@ public function getDetailed(): bool { } + /** + * Returns the template for the given name (override if set, default + * otherwise). + * + * @param string $name + * + * @return string + */ + public function getTemplate(string $name): string + { + } + /** * Alias of variable() method * @@ -110,6 +134,18 @@ public function setStyles(array $styles = []): array { } + /** + * Overrides the template for the given name. + * + * @param string $name + * @param string $template + * + * @return static + */ + public function setTemplate(string $name, string $template): static + { + } + /** * Returns an JSON string of information about a single variable. * @@ -166,6 +202,17 @@ public function variables(): string { } + /** + * Returns the embedded default template for the given name. + * + * @param string $name + * + * @return string + */ + protected function defaultTemplate(string $name): string + { + } + /** * Get style for type * @@ -187,4 +234,13 @@ protected function getStyle(string $type): string protected function output($variable, ?string $name = null, int $tab = 1): string { } + + /** + * @param string $text + * + * @return string + */ + private function getOutputBold(string $text): string + { + } } diff --git a/src/Support/Debug/Renderer/HtmlRenderer.php b/src/Support/Debug/Renderer/HtmlRenderer.php new file mode 100644 index 00000000..a2101bcd --- /dev/null +++ b/src/Support/Debug/Renderer/HtmlRenderer.php @@ -0,0 +1,242 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Support\Debug\Renderer; + +use Phalcon\Contracts\Support\Debug\Renderer; +use Phalcon\Support\Debug\Report\BacktraceItem; +use Phalcon\Support\Debug\Report\ExceptionReport; +use Phalcon\Support\Version; + +/** + * Renders an ExceptionReport as the HTML debug page using embedded, overridable + * template strings filled by strtr. All styling and interactivity (theme, tabs, + * syntax highlighting, copy/editor links) are provided by the external + * debug.css / debug.js assets. + */ +class HtmlRenderer implements \Phalcon\Contracts\Support\Debug\Renderer +{ + /** + * Template overrides keyed by name. + * + * @todo Move getTemplate()/setTemplate()/templates into a shared trait once + * Zephir supports traits (mirrors + * Phalcon\Support\Debug\Traits\TemplateAwareTrait in the PHP source). + * + * @var array + */ + protected $templates = []; + + /** + * @param string $uri + * + * @return string + */ + public function getCssSources(string $uri): string + { + } + + /** + * @param string $uri + * + * @return string + */ + public function getJsSources(string $uri): string + { + } + + /** + * Returns the template for the given name (override if set, default + * otherwise). + * + * @param string $name + * + * @return string + */ + public function getTemplate(string $name): string + { + } + + /** + * @return string + */ + public function getVersion(): string + { + } + + /** + * @param ExceptionReport $report + * + * @return string + */ + public function render(\Phalcon\Support\Debug\Report\ExceptionReport $report): string + { + } + + /** + * Overrides the template for the given name. + * + * @param string $name + * @param string $template + * + * @return static + */ + public function setTemplate(string $name, string $template): static + { + } + + /** + * Returns the embedded default template for the given name. + * + * @param string $name + * + * @return string + */ + protected function defaultTemplate(string $name): string + { + } + + /** + * Escapes a string with htmlentities + * + * @param string $value + * + * @return string + */ + protected function escapeString(string $value): string + { + } + + /** + * Produces a recursive representation of an array + * + * @param array $argument + * @param int $n + * + * @return string|null + * @param int $number + */ + protected function getArrayDump(array $argument, int $number = 0): string|null + { + } + + /** + * Produces a string representation of a variable + * + * @param mixed $variable + * + * @return string + */ + protected function getVarDump($variable): string + { + } + + /** + * @param int $bytes + * + * @return string + */ + private function formatBytes(int $bytes): string + { + } + + /** + * Frames whose file lives outside a vendor directory are application code. + * + * @param string|null $file + * + * @return bool + */ + private function isApp($file): bool + { + } + + /** + * @param BacktraceItem[] $backtrace + * + * @return string + */ + private function renderBacktrace(array $backtrace): string + { + } + + /** + * @param array $fragment + * + * @return string + */ + private function renderFragment(array $fragment): string + { + } + + /** + * @param array $files + * + * @return string + */ + private function renderIncludedFiles(array $files): string + { + } + + /** + * @param ExceptionReport $report + * + * @return string + */ + private function renderMemory(\Phalcon\Support\Debug\Report\ExceptionReport $report): string + { + } + + /** + * @param BacktraceItem $item + * + * @return string + */ + private function renderSignature(\Phalcon\Support\Debug\Report\BacktraceItem $item): string + { + } + + /** + * @param string $div + * @param array $source + * + * @return string + */ + private function renderSuperglobal(string $div, array $source): string + { + } + + /** + * @param ExceptionReport $report + * + * @return string + */ + private function renderTabs(\Phalcon\Support\Debug\Report\ExceptionReport $report): string + { + } + + /** + * @param int $index + * @param BacktraceItem $item + * + * @return string + */ + private function renderTraceItem(int $index, \Phalcon\Support\Debug\Report\BacktraceItem $item): string + { + } + + /** + * @param array $variables + * + * @return string + */ + private function renderVariables(array $variables): string + { + } +} diff --git a/src/Support/Debug/Report/BacktraceItem.php b/src/Support/Debug/Report/BacktraceItem.php new file mode 100644 index 00000000..b8fde507 --- /dev/null +++ b/src/Support/Debug/Report/BacktraceItem.php @@ -0,0 +1,152 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Support\Debug\Report; + +/** + * Represents a single resolved frame of an exception backtrace. + */ +final class BacktraceItem +{ + /** + * @var array + */ + protected $args = []; + + /** + * @var string|null + */ + protected $classLink = null; + + /** + * @var string|null + */ + protected $className = null; + + /** + * @var string|null + */ + protected $file = null; + + /** + * @var array|null + */ + protected $fragment = null; + + /** + * @var string|null + */ + protected $functionLink = null; + + /** + * @var string + */ + protected $functionName; + + /** + * @var bool + */ + protected $hasArgs = false; + + /** + * @var int|null + */ + protected $line = null; + + /** + * @var string|null + */ + protected $type = null; + + /** + * @param string $functionName + * @param string|null $type + * @param string|null $className + * @param string|null $classLink + * @param string|null $functionLink + * @param bool $hasArgs + * @param array $args + * @param string|null $file + * @param int|null $line + * @param array|null $fragment + */ + public function __construct(string $functionName, $type = null, $className = null, $classLink = null, $functionLink = null, bool $hasArgs = false, array $args = [], $file = null, $line = null, $fragment = null) + { + } + + /** + * @return array + */ + public function getArgs(): array + { + } + + /** + * @return string|null + */ + public function getClassLink(): string|null + { + } + + /** + * @return string|null + */ + public function getClassName(): string|null + { + } + + /** + * @return string|null + */ + public function getFile(): string|null + { + } + + /** + * @return array|null + */ + public function getFragment(): array|null + { + } + + /** + * @return string|null + */ + public function getFunctionLink(): string|null + { + } + + /** + * @return string + */ + public function getFunctionName(): string + { + } + + /** + * @return int|null + */ + public function getLine(): int|null + { + } + + /** + * @return string|null + */ + public function getType(): string|null + { + } + + /** + * @return bool + */ + public function hasArgs(): bool + { + } +} diff --git a/src/Support/Debug/Report/ExceptionReport.php b/src/Support/Debug/Report/ExceptionReport.php new file mode 100644 index 00000000..1a689ea5 --- /dev/null +++ b/src/Support/Debug/Report/ExceptionReport.php @@ -0,0 +1,255 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Support\Debug\Report; + +/** + * Carries all data collected for an exception, ready to be rendered. Holds no + * presentation logic. + */ +final class ExceptionReport +{ + /** + * @var BacktraceItem[] + */ + protected $backtrace = []; + + /** + * @var string + */ + protected $className; + + /** + * @var string + */ + protected $file; + + /** + * @var array + */ + protected $includedFiles = []; + + /** + * @var int + */ + protected $line; + + /** + * @var int + */ + protected $memoryUsage = 0; + + /** + * @var string + */ + protected $message; + + /** + * @var int + */ + protected $peakMemoryUsage = 0; + + /** + * @var array + */ + protected $request = []; + + /** + * @var array + */ + protected $server = []; + + /** + * @var bool + */ + protected $showBackTrace; + + /** + * @var string + */ + protected $uri; + + /** + * @var array + */ + protected $variables = []; + + /** + * @param string $className + * @param string $message + * @param string $file + * @param int $line + * @param bool $showBackTrace + * @param string $uri + */ + public function __construct(string $className, string $message, string $file, int $line, bool $showBackTrace, string $uri) + { + } + + /** + * @return BacktraceItem[] + */ + public function getBacktrace(): array + { + } + + /** + * @return string + */ + public function getClassName(): string + { + } + + /** + * @return string + */ + public function getFile(): string + { + } + + /** + * @return array + */ + public function getIncludedFiles(): array + { + } + + /** + * @return int + */ + public function getLine(): int + { + } + + /** + * @return int + */ + public function getMemoryUsage(): int + { + } + + /** + * @return string + */ + public function getMessage(): string + { + } + + /** + * @return int + */ + public function getPeakMemoryUsage(): int + { + } + + /** + * @return array + */ + public function getRequest(): array + { + } + + /** + * @return array + */ + public function getServer(): array + { + } + + /** + * @return string + */ + public function getUri(): string + { + } + + /** + * @return array + */ + public function getVariables(): array + { + } + + /** + * @return bool + */ + public function hasVariables(): bool + { + } + + /** + * @return bool + */ + public function isShowBackTrace(): bool + { + } + + /** + * @param BacktraceItem[] $backtrace + * + * @return static + */ + public function setBacktrace(array $backtrace): static + { + } + + /** + * @param array $includedFiles + * + * @return static + */ + public function setIncludedFiles(array $includedFiles): static + { + } + + /** + * @param int $memoryUsage + * + * @return static + */ + public function setMemoryUsage(int $memoryUsage): static + { + } + + /** + * @param int $peakMemoryUsage + * + * @return static + */ + public function setPeakMemoryUsage(int $peakMemoryUsage): static + { + } + + /** + * @param array $request + * + * @return static + */ + public function setRequest(array $request): static + { + } + + /** + * @param array $server + * + * @return static + */ + public function setServer(array $server): static + { + } + + /** + * @param array $variables + * + * @return static + */ + public function setVariables(array $variables): static + { + } +} diff --git a/src/Support/Debug/ReportBuilder.php b/src/Support/Debug/ReportBuilder.php new file mode 100644 index 00000000..e837ddb8 --- /dev/null +++ b/src/Support/Debug/ReportBuilder.php @@ -0,0 +1,95 @@ + + * + * For the full copyright and license information, please view the LICENSE.txt + * file that was distributed with this source code. + */ +namespace Phalcon\Support\Debug; + +use Phalcon\Support\Debug\Report\BacktraceItem; +use Phalcon\Support\Debug\Report\ExceptionReport; +use Phalcon\Support\Helper\Arr\Get; +use ReflectionClass; +use ReflectionException; +use ReflectionFunction; +use Throwable; + +/** + * Collects the runtime data for an exception (backtrace, superglobals, included + * files, memory, variables) into an ExceptionReport. Holds no presentation + * logic. + */ +class ReportBuilder +{ + /** + * @param Throwable $exception + * @param array $blacklist + * @param bool $showBackTrace + * @param bool $showFiles + * @param bool $showFileFragment + * @param string $uri + * @param array $data + * + * @return ExceptionReport + * @throws ReflectionException + */ + public function build(\Throwable $exception, array $blacklist, bool $showBackTrace, bool $showFiles, bool $showFileFragment, string $uri, array $data): ExceptionReport + { + } + + /** + * @param string $file + * @param int $line + * @param bool $showFileFragment + * + * @return array + */ + private function buildFragment(string $file, int $line, bool $showFileFragment): array + { + } + + /** + * @param array $trace + * @param bool $showFiles + * @param bool $showFileFragment + * + * @return BacktraceItem + * @throws ReflectionException + */ + private function buildItem(array $trace, bool $showFiles, bool $showFileFragment): BacktraceItem + { + } + + /** + * @param array $source + * @param array $blacklist + * + * @return array + */ + private function filter(array $source, array $blacklist): array + { + } + + /** + * @param string $className + * + * @return string|null + * @throws ReflectionException + */ + private function resolveClassLink(string $className): string|null + { + } + + /** + * @param string $functionName + * + * @return string|null + * @throws ReflectionException + */ + private function resolveFunctionLink(string $functionName): string|null + { + } +}