-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathzero.mbt
More file actions
155 lines (136 loc) · 4.29 KB
/
Copy pathzero.mbt
File metadata and controls
155 lines (136 loc) · 4.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
///|
/// The default port a moonzero service listens on.
///
/// 12000 is the family's number, not go-zero's 8888: every example, every
/// document and every local run in this ecosystem points at the same place, and
/// on a development machine 8888 is somebody else's already.
pub let port : Int = 12000
///|
/// The default port the zRPC server listens on.
///
/// gRPC shares 12000 with HTTP wherever one listener carries both, but a
/// moonzero process binds `RestEngine` and `RpcServer` separately — two
/// listeners cannot hold one port — so the second takes the next number.
pub let rpc_port : Int = 12001
///|
/// Log verbosity (← go-zero's `LogConf.Level`), ordered from most to least
/// verbose. `Compare` follows that order so thresholds can be tested directly.
pub(all) enum LogLevel {
Debug
Info
Error
Severe
} derive(Eq, Compare, Debug)
///|
/// The canonical lowercase name go-zero uses on the wire.
pub fn LogLevel::to_string(self : LogLevel) -> String {
match self {
Debug => "debug"
Info => "info"
Error => "error"
Severe => "severe"
}
}
///|
/// The `moonlog` level this one records as. go-zero's ladder has four rungs and
/// `moonlog`'s has six, so the map is one-way: `Severe` records as `Fatal`, and
/// [`level_name`] writes it back out as `severe`.
pub fn LogLevel::as_level(self : LogLevel) -> @moonlog.Level {
match self {
Debug => Debug
Info => Info
Error => Error
Severe => Fatal
}
}
///|
/// Parse a level name, falling back to `Info` for anything unrecognised — the
/// same lenient default go-zero applies to a missing/empty level.
pub fn LogLevel::parse(s : String) -> LogLevel {
match s {
"debug" => Debug
"error" => Error
"severe" => Severe
_ => Info
}
}
///|
/// Service configuration (← go-zero's `ServiceConf`): the service name, its bind
/// address, a request timeout, and the log level. `timeout_ms` is the per-request
/// budget in milliseconds; `0` disables the deadline.
pub(all) struct ServiceConf {
name : String
host : String
port : Int
timeout_ms : Int
log_level : LogLevel
} derive(FromJson, Eq)
///|
/// Build a config with sensible defaults (`0.0.0.0:12000`, 3s timeout, `info`).
pub fn ServiceConf::new(
name? : String = "app",
host? : String = "0.0.0.0",
port? : Int = port,
timeout_ms? : Int = 3000,
log_level? : LogLevel = Info,
) -> ServiceConf {
{ name, host, port, timeout_ms, log_level, }
}
///|
/// An AsgiApp transformer — one layer of the middleware onion.
pub type Middleware = (@moonasgi.AsgiApp) -> @moonasgi.AsgiApp
///|
/// A moonzero service: its config plus the assembled application (a moonapi App
/// with any middleware already wrapped around it).
pub struct Server {
conf : ServiceConf
handler : @moonasgi.AsgiApp
}
///|
/// Assemble a service from config and a moonapi application.
pub fn Server::new(conf : ServiceConf, app : @moonapi.App) -> Server {
{ conf, handler: app.to_asgi(), }
}
///|
/// Wrap the current application in another middleware layer (outermost last).
pub fn Server::use_(self : Server, mw : Middleware) -> Server {
{ conf: self.conf, handler: mw(self.handler), }
}
///|
/// The assembled `AsgiApp`, ready for a server (mooncat) to run.
pub fn Server::to_asgi(self : Server) -> @moonasgi.AsgiApp {
self.handler
}
///|
/// A human-readable description of what this service binds to.
pub fn Server::describe(self : Server) -> String {
self.conf.name +
" listening on " +
self.conf.host +
":" +
self.conf.port.to_string()
}
///|
/// A request-logging middleware: writes `METHOD path` through the process `logx`
/// at `info` for each HTTP request, then delegates to the wrapped application.
/// It logs on the way in and knows nothing of the response; `structured_logging`
/// is the layer that times the request and records its status.
pub fn logging(inner : @moonasgi.AsgiApp) -> @moonasgi.AsgiApp {
(scope, receive, send) => {
match scope {
Http(hs) => logx.info(hs.http_method + " " + hs.path)
_ => ()
}
inner(scope, receive, send)
}
}
///|
pub extend LogLevel with Compare::{op_lt, op_le, op_ge, compare, op_gt}
///|
pub extend LogLevel with Debug::{to_repr}
///|
pub extend LogLevel with Eq::{not_equal, equal}
///|
pub extend LogLevel with FromJson::{from_json}
///|
pub extend ServiceConf with Eq::{not_equal, equal}