1515
1616A simple queue: messages, handlers and workers.
1717
18+ ## Why this exists
19+
20+ A queue has one hard requirement and everything else is convenience: ** a message has to survive
21+ being written down in one process and read back in another** . That is why a message here carries
22+ only what it is about, and what to do with it is a separate class the container builds — a
23+ message holding its own dependencies cannot be written down at all.
24+
25+ The rest is what an application actually needs from a queue and no more: a delay, named queues,
26+ retries with a backoff, and somewhere for the messages that will not work to sit so they are not
27+ in the way of the ones behind them.
28+
29+ ## Requirements
30+
31+ - PHP 8.1 or newer
32+
1833## Installation
1934
2035``` shell
2136composer require quillstack/queue
2237```
2338
24- ## Messages and handlers
39+ ## Usage
40+
41+ ### Messages and handlers
2542
2643A message carries only what it is about. What is done with it is a handler, built by the
2744container, which asks for what it needs through its constructor:
@@ -58,7 +75,7 @@ $handlers->handle(SendWelcomeEmail::class, SendWelcomeEmailHandler::class);
5875A handler registered for a class answers anything extending or implementing it, so one
5976handler can take a whole family of messages through an interface they share.
6077
61- ## Pushing
78+ ### Pushing
6279
6380``` php
6481$queue->push(new SendWelcomeEmail('radek@quillstack.com'));
@@ -72,7 +89,7 @@ $queue->push(new SendReminder($id), 'emails', 3600);
7289$queue->push(new ChargeCard($id), delay: new DateInterval('PT5M'));
7390```
7491
75- ## Working
92+ ### Working
7693
7794``` php
7895$worker = new Worker($queue, $handlers, $container, tries: 3, backoff: 10);
@@ -90,7 +107,7 @@ nobody handles is set aside at once: waiting will not give it a handler.
90107$queue->failed(); // the messages which will not be tried again
91108```
92109
93- ## Where the messages live
110+ ### Where the messages live
94111
95112` ArrayQueue ` keeps them for as long as the process runs, which is what a test wants and what
96113a single request needs when whatever it queued is handled before the response goes out.
@@ -105,12 +122,41 @@ $queue = new FileQueue(new LocalStorage(), __DIR__ . '/var/queue');
105122The file is taken away before the message is handed over, so two workers reading the same
106123directory cannot both be given it.
107124
108- ## Time
125+ ### Time
109126
110127Both take a PSR-20 clock, which decides when a message is due. Without one they read the
111128wall clock. ` Quillstack\Clock\FrozenClock ` stands still until it is moved, so a test can
112129watch a delay pass without waiting for it.
113130
131+ ## Benchmark
132+
133+ Measured with [ quillstack/benchmark] ( https://github.com/quillstack/benchmark ) on a thousand
134+ messages pushed and handled in memory. Runs are interleaved and unconcurrent, each figure is the
135+ median of five, and PHP is 8.5.7.
136+
137+ | | Version |
138+ | --- | --- |
139+ | quillstack/queue | v0.6.0 |
140+ | symfony/messenger | v7.4.17 |
141+
142+ | | Per message | Relative |
143+ | --- | --- | --- |
144+ | ** quillstack/queue** | ** 1.48 µs** | — |
145+ | symfony/messenger | 2.29 µs | 1.5× |
146+
147+ ** A microsecond either way is not what a queue costs.** What a queue costs is the transport — a
148+ row written to a database, a message sent to Redis, an HTTP call to SQS — and that is three or
149+ four orders of magnitude more than either number here. This table measures the part that does not
150+ matter, and says so.
151+
152+ What matters is what each reaches. ` symfony/messenger ` has transports for AMQP, Redis, Doctrine,
153+ Amazon SQS, Beanstalkd and more, message serialization across processes, routing rules, retry
154+ strategies you can replace, failure transports, and a middleware stack around handling. This has
155+ an array, a directory of files, and a worker.
156+
157+ If your messages leave this machine, use Messenger. If they need to survive a restart and be
158+ picked up by a worker on the same box, this is a great deal less to understand.
159+
114160## Tests
115161
116162``` shell
@@ -123,6 +169,16 @@ Coverage needs phpdbg:
123169composer test:coverage
124170```
125171
172+ ## The rest of Quillstack
173+
174+ This is one component of [ Quillstack] ( https://github.com/quillstack ) , a PHP framework which is
175+ as simple to use as it is strict about what it does.
176+
177+ - [ quillstack/di] ( https://github.com/quillstack/di ) — what builds a handler
178+ - [ quillstack/clock] ( https://github.com/quillstack/clock ) — what decides whether a message is due
179+ - [ quillstack/logger] ( https://github.com/quillstack/logger ) — where a message that failed is written
180+ - [ quillstack/framework] ( https://github.com/quillstack/framework ) — where the worker command lives
181+
126182## License
127183
128184MIT. See [ LICENSE] ( LICENSE ) .
0 commit comments