@@ -11,46 +11,51 @@ This repository is the scaffold of the Thunder CLI micro-framework.
11
11
You can use it and modify the structure to adapt on your needs.
12
12
13
13
## Philosophy
14
- Sometimes you just need a very simple deamon, eventloop based, when you're event programming.
15
- A small repository for your boundary, with few dependencies, and don't want to
14
+ Sometimes you just need a very simple deamon, eventloop based, when you're event programming.
15
+ A small repository for your boundary, with few dependencies, and don't want to
16
16
be force to use a library or an other.
17
17
18
- All you need is a reaction to an event that has been occurred in your system,
18
+ All you need is a reaction to an event that has been occurred in your system,
19
19
externally or internally (pub/sub or saga f.e.).
20
20
21
- However, this project is born inside a repository using Reactive Programming
22
- by default, RabbitMQ consumers, a router, EventStore projections and events,
21
+ However, this project is born inside a repository using Reactive Programming
22
+ by default, RabbitMQ consumers, a router, EventStore projections and events,
23
23
mysql, Redis connectors, and many more.
24
24
25
25
Simple but powerful.
26
26
27
27
## What built in
28
28
### Console Component
29
- The whole concept is base on consoles.
29
+ The whole concept is based on consoles.
30
30
Instead of reinvent the wheel, Thunder use [ Silly] ( https://github.com/mnapoli/silly )
31
- micro-framework. An ` AbstractConsole ` is provided by the framework, allowing
32
- classes extending it to be automatically loaded and usable.
31
+ micro-framework. A ` Console ` class being provided by the framework, allowing
32
+ classes that extend it to be automatically loaded and usable.
33
33
34
34
### Dependency Injection
35
- Usage of the dependency injection pattern, ease decoupling your code and quality
35
+ Usage of the dependency injection pattern, ease decoupling your code and quality
36
36
test writing. [ Symfony DI] ( https://symfony.com/doc/current/components/dependency_injection.html )
37
37
component has been chosen for it many features [ ] ( https://symfony.com/doc/current/components/dependency_injection.html#learn-more )
38
- improving developer experience.
38
+ improving developer experience.
39
39
40
40
### Configuration Component
41
- This component allows you to use XML, YAML & PHP files. You can access and use
41
+ This component allows you to use XML, YAML & PHP files. You can access and use
42
42
them directly into constructors through DI.
43
43
44
44
### Router
45
- This component is central in the project, Command Bus and Event Dispatcher
45
+ This component is central in the project, Command Bus and Event Dispatcher
46
46
pattern aren't adapted to non acknowledge (` nack ` ) messages.
47
47
48
- It force to use [ Subjects] ( http://reactivex.io/documentation/subject.html ) in cases
49
- where ` ack/nack ` is necessary on the message.
48
+ It's pretty straight forward, a ` Route ` can be associated to a ` Controller ` in a
49
+ MVC schema. The core provide a base class called ` Route ` that allow to
50
+ automatically load all classes extending it in the ` Router ` .
50
51
51
- It needs some ` AbstractRoute ` and send an ` AbstractSubject ` to the right one.
52
- An ` AbstractRoute ` can be associated to a ` Controller ` in traditional software
53
- architecture pattern.
52
+ Each route have to define it's constant called ` PATH ` . It's used to determine
53
+ which ` Route ` of your application must be invoked.
54
+
55
+ As we are in an event driven framework, all ` Route ` must return an ` Observable ` .
56
+ The different plugins that you will use in your application, are subscribing to
57
+ your ` Observable ` using ` Observers ` to determine actions to execute at the end
58
+ of your event chain.
54
59
55
60
## Installation
56
61
@@ -65,31 +70,24 @@ To start the project you need to execute a PHP file available in the vendors, `v
65
70
66
71
All commands available will be prompted.
67
72
68
- ### Subject
69
- When your are consuming a source of data, each message is converted into an
70
- ` AbstractSubject ` . This subject is an ` Observable ` & an ` Observer ` with some
71
- subscribers already plugged.
72
-
73
- One of the subscribers is responsible to handle the ` acknowledge/non-acknowledge ` behavior.
74
-
75
- So basically, when the subject is completed, the message is acknowledged, and
76
- you will received a new message when available.
77
-
78
73
### Create a new Route
79
- Just extends the ` Th3Mouk\Thunder\Route\AbstractRoute ` into ` /src ` and it will
74
+ Create a class extending ` Th3Mouk\Thunder\Router\Route ` into ` /src ` and it will
80
75
be automatically added to the router.
81
76
82
- You can modify the ` config/services.php ` and ` composer.json ` autoload if you
77
+ You can modify the ` config/services.php ` and ` composer.json ` autoload if you
83
78
don't want to use ` src ` folder.
84
79
80
+ Your ` Route ` will now be invoked with the corresponding ` DataModel ` through
81
+ the PATH constant.
82
+
85
83
#### Extra: Handler concept
86
84
I personally use ` src/route ` and ` src/handler ` structure.
87
85
The term ` handler ` coming from the Command Bus pattern.
88
86
89
- An handler here, is a small invokable unit that can be reused in multiple
87
+ An handler here, is a small invokable unit that can be reused in multiple
90
88
contexts, sagas of events, or here again routes.
91
- The main advantage of this, is you can decouple your code and test it correctly,
92
- because yes, this handler will be automatically injected in the container,
89
+ The main advantage of this, is you can decouple your code and test it correctly,
90
+ because yes, this handler will be automatically injected in the container,
93
91
and you can use DI in its constructor :tada : .
94
92
95
93
An example can be:
@@ -98,13 +96,13 @@ An example can be:
98
96
namespace App\Handler;
99
97
100
98
use Rx\Observable;
101
- use Th3Mouk\Thunder\Router\AbstractSubject ;
99
+ use RxThunder\Core\Model\DataModel ;
102
100
103
101
class PromptHello
104
102
{
105
- public function __invoke(AbstractSubject $subject )
103
+ public function __invoke(DataModel $data_model )
106
104
{
107
- return Observable::of($subject )
105
+ return Observable::of($data_model )
108
106
->do(function() {
109
107
echo "hello there". PHP_EOL;
110
108
});
@@ -120,10 +118,10 @@ namespace App\Route;
120
118
121
119
use App\Handler\PromptHello;
122
120
use Rx\Observable;
123
- use Th3Mouk\Thunder\Router\AbstractRoute ;
124
- use Th3Mouk\Thunder \Router\AbstractSubject ;
121
+ use RxThunder\Core\Model\DataModel ;
122
+ use RxThunder\Core \Router\Route ;
125
123
126
- class Test extends AbstractRoute
124
+ class Test extends Route
127
125
{
128
126
public const PATH = '/test';
129
127
@@ -135,34 +133,27 @@ class Test extends AbstractRoute
135
133
$this->prompt = $prompt;
136
134
}
137
135
138
- public function __invoke(AbstractSubject $subject)
136
+ public function __invoke(DataModel $data_model): Observable
139
137
{
140
- return Observable::of($subject )
138
+ return Observable::of($data_model )
141
139
->do(function () {
142
140
echo "i'm in /test".PHP_EOL;
143
141
})
144
142
->flatMap($this->prompt)
145
143
->do(function () {
146
144
echo "passed in /test".PHP_EOL;
147
- })
148
- ->subscribe(function (AbstractSubject $subject) {
149
- $subject->onCompleted();
150
145
});
151
146
}
152
147
}
153
148
```
154
149
155
150
### Start consuming
156
- If you use the RabbitMq consumer you can start with ` php console listen:broker:rabbit test default `
157
- ` test ` is the name of the queue to consume
158
- ` default ` is the name of the connection to use
159
-
160
- The connection system and configuration of RabbitMq is not documented yet and
161
- probably will be extracted into a plug & play plugin.
151
+ If you use the RabbitMQ plugin you can start consuming a queue with
152
+ ` php console rabbit:listen:broker test `
153
+ (` test ` is the name of the queue to consume)
162
154
163
- Each message received by the queue will be transformed into a ` RabbitMq/Subject `
164
- and the ** routing key** is the pattern the router is looking into the collection
165
- of routes.
155
+ Each message received by the queue will be transformed into a ` DataModel `
156
+ and the ** routing key** correspond to the ` type() ` of it.
166
157
167
- For example a message with ` /test ` routing key in Rabbit will be consumed by
168
- the route with ` public const PATH = '/test'; `
158
+ For example a message with ` /test ` routing key in RabbitMQ will be consumed by
159
+ the route with ` public const PATH = '/test'; `
0 commit comments