Skip to content

Commit 0d6c6d8

Browse files
authored
Merge pull request #3 from schultyy/refactor-services
Refactor: Implement Service-to-Service Communication and Code Generation
2 parents 2008704 + d7d12b2 commit 0d6c6d8

22 files changed

+2825
-1255
lines changed

Cargo.lock

Lines changed: 763 additions & 62 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,27 @@ edition = "2021"
88

99
[dependencies]
1010
tracing = { version = "0.1", features = ["log", "log-always"] }
11-
tracing-subscriber = { version = "0.3.3", features = ["std", "env-filter"] }
11+
tracing-subscriber = { version = "0.3.19", features = ["env-filter", "json"] }
1212
clap = { version = "4.4", features = ["derive"] }
1313
fake = { version = "4", features = ["derive"] }
14-
tracing-opentelemetry = "0.28.0"
15-
opentelemetry = "0.27"
16-
opentelemetry-otlp = "0.27.0"
17-
opentelemetry_sdk = { version = "0.27.1", features = [
18-
"opentelemetry-http",
14+
tracing-opentelemetry = "0.29.0"
15+
opentelemetry = "0.29.0"
16+
opentelemetry-otlp = { version = "0.29.0", features = ["tonic", "grpc-tonic"] }
17+
opentelemetry_sdk = { version = "0.29.0", features = [
1918
"rt-tokio",
19+
"tokio",
20+
"opentelemetry-http",
2021
] }
2122
tonic = "0.12.3"
22-
opentelemetry-appender-tracing = "0.27"
23-
opentelemetry-stdout = "0.27.0"
23+
opentelemetry-appender-tracing = "0.29.0"
24+
opentelemetry-stdout = "0.29.0"
2425
tokio = { version = "1.43.0", features = ["full"] }
2526
futures = "0.3"
2627
rand = "0.9.0"
2728
ctrlc = "3.4"
2829
serde = { version = "1.0.219", features = ["derive"] }
2930
serde_yaml = "0.9.34"
3031
opentelemetry-semantic-conventions = "0.29.0"
32+
pest = "2.8.0"
33+
pest_derive = "2.8.0"
34+
tabled = "0.18.0"

README.md

Lines changed: 113 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -42,72 +42,124 @@ mustermann [OPTIONS] <file_path> [otel_endpoint] [--service-name <service_name>]
4242
mustermann config.yaml http://localhost:4317 --service-name my-service
4343
```
4444

45-
## Configuration
46-
47-
### Log Configuration
48-
49-
Define log patterns and their execution behavior:
50-
51-
```yaml
52-
- task_name: App Logs
53-
frequency: Infinite
54-
template: "User %s logged in"
55-
vars:
56-
- Franz Josef
57-
- 34
58-
- Heinz
59-
severity: INFO
60-
- task_name: App Login Errors
61-
frequency: Amount(45)
62-
template: "Failed to login: %s"
63-
vars:
64-
- Invalid username or password
65-
- Upstream connection refused
66-
severity: ERROR
45+
Standalone service just printing values:
46+
47+
```
48+
service payments {
49+
method charge {
50+
print "Processing payment for order %s" with ["12345", "67890"]
51+
sleep 500ms
52+
}
53+
54+
loop {
55+
call charge
56+
}
57+
}
58+
```
59+
60+
Standalone service printing values to stderr:
61+
62+
```
63+
service payments {
64+
method charge {
65+
stderr "Processing payment for order %s" with ["12345", "67890"]
66+
sleep 500ms
67+
}
68+
69+
loop {
70+
call charge
71+
}
72+
}
73+
```
74+
75+
Service accepting requests from other services:
76+
77+
```
78+
service payments {
79+
method charge {
80+
print "Processing payment for order %s" with ["12345", "67890"]
81+
sleep 500ms
82+
}
83+
}
84+
```
85+
86+
Call another service:
87+
88+
```
89+
service products {
90+
method get_products {
91+
print "Fetching product orders %s" with ["12345", "67890"]
92+
sleep 500ms
93+
}
94+
}
95+
96+
service frontend {
97+
method main_page {
98+
print "Main page"
99+
call products.get_products
100+
}
101+
102+
loop {
103+
call main_page
104+
}
105+
}
67106
```
68107

69-
### Service Configuration
70-
71-
Define interconnected services and their interactions:
72-
73-
```yaml
74-
logs: []
75-
services:
76-
- name: checkout
77-
methods:
78-
- name: process
79-
stdout: Processing Order
80-
sleep_ms: 100
81-
- name: user_service
82-
methods:
83-
- name: get_user
84-
stdout: Getting user
85-
sleep_ms: 100
86-
- name: product_service
87-
methods:
88-
- name: get_product
89-
stdout: Getting product
90-
sleep_ms: 100
91-
- name: web_frontend
92-
methods:
93-
- name: start_checkout
94-
stdout: Starting checkout
95-
calls:
96-
- name: product_service
97-
method: get_product
98-
- name: user_service
99-
method: get_user
100-
- name: checkout
101-
method: process
102-
sleep_ms: 100
103-
invoke:
104-
- start_checkout
108+
## Multi-service example
109+
110+
```
111+
service products {
112+
method get_products {
113+
print "Fetching product orders %s" with ["12345", "67890"]
114+
sleep 500ms
115+
}
116+
}
117+
118+
service features {
119+
method is_enabled {
120+
print "Check if feature is enabled %s" with ["login", "upload", "create"]
121+
sleep 1000ms
122+
}
123+
}
124+
125+
service frontend {
126+
method login {
127+
print "Main page"
128+
call features.is_enabled
129+
}
130+
131+
loop {
132+
call login
133+
}
134+
}
135+
136+
service analytics {
137+
method main_page {
138+
print "Main page"
139+
call products.get_products
140+
}
141+
142+
loop {
143+
call main_page
144+
}
145+
}
146+
147+
148+
service frontend_b {
149+
method main_page {
150+
print "Main page"
151+
call products.get_products
152+
}
153+
154+
loop {
155+
call main_page
156+
}
157+
}
105158
```
106159

107-
- Services can invoke each other's methods.
108-
- If no `invoke` is specified, the service just runs in an infinite loop, waiting for invokations.
160+
This service definition will generate the following service map:
109161

110-
![screenshot.png](screenshot.png)
162+
![servicemap](servicemap.png)
111163

112164
## License
113165

example.yml

Lines changed: 0 additions & 19 deletions
This file was deleted.

multi_service.muster

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
service products {
2+
method get_products {
3+
print "Fetching product orders %s" with ["12345", "67890"]
4+
sleep 500ms
5+
}
6+
}
7+
8+
service features {
9+
method is_enabled {
10+
print "Check if feature is enabled %s" with ["login", "upload", "create"]
11+
sleep 1000ms
12+
}
13+
}
14+
15+
service frontend {
16+
method login {
17+
print "Main page"
18+
call features.is_enabled
19+
}
20+
21+
loop {
22+
call login
23+
}
24+
}
25+
26+
service analytics {
27+
method main_page {
28+
print "Main page"
29+
call products.get_products
30+
}
31+
32+
loop {
33+
call main_page
34+
}
35+
}
36+
37+
38+
service frontend_b {
39+
method main_page {
40+
print "Main page"
41+
call products.get_products
42+
}
43+
44+
loop {
45+
call main_page
46+
}
47+
}

servicemap.png

133 KB
Loading

services.muster

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
service payments {
2+
method charge {
3+
print "Processing payment for order %s" with ["12345", "67890"]
4+
sleep 500ms
5+
stderr "Processing payment for order %s" with ["BANANAS AND APPLES"]
6+
}
7+
8+
loop {
9+
call charge
10+
}
11+
}

services.yml

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/code_gen/error.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
#[derive(Debug, Clone, PartialEq, Eq)]
2-
pub enum ByteCodeError {
3-
UnsupportedConst(String),
1+
#[derive(Debug, Clone)]
2+
pub enum CodeGenError {
3+
InvalidStatement(String),
44
}
55

6-
impl std::error::Error for ByteCodeError {}
7-
8-
impl std::fmt::Display for ByteCodeError {
6+
impl std::fmt::Display for CodeGenError {
97
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108
match self {
11-
ByteCodeError::UnsupportedConst(val) => write!(f, "Unsupported constant: {}", val),
9+
CodeGenError::InvalidStatement(msg) => write!(f, "Invalid statement: {}", msg),
1210
}
1311
}
1412
}
13+
14+
impl std::error::Error for CodeGenError {}

0 commit comments

Comments
 (0)