kirei 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/cli/commands/new_app/files/app.rb +4 -1
- data/lib/cli/commands/new_app/files/routes.rb +2 -30
- data/lib/kirei/controllers/health.rb +63 -0
- data/lib/kirei/routing/base.rb +31 -8
- data/lib/kirei/routing/router.rb +12 -0
- data/lib/kirei/routing/verb.rb +0 -6
- data/lib/kirei/version.rb +1 -1
- data/lib/kirei.rb +1 -3
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1926e641bc2fa378b9444e97f33c7aef0bd97ce3c277a38fc572f12d501acb77
|
|
4
|
+
data.tar.gz: 2cdaff92504ea20fac445d791da1f9557fe3fbe6f4f780eab70c9022feacb3e1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4111679c635210bd6a9389c839c2665e5fea9a1e4bd3e6186725e89022a8964cf7a2dc8c2b5347eaf76962b327a7c0a77243cfc7c6ac214e01f59592a08a132f
|
|
7
|
+
data.tar.gz: 8aaf9c748f52d790cc2be69cb29087c96f1ad1001ee629555b5727d93770a1b73be72fbb62a8d1b3993a3ef75676832463b401cb265e5dd18a277d9706b9fc68
|
data/README.md
CHANGED
|
@@ -6,7 +6,7 @@ Kirei's main advantages over other frameworks are its strict typing, low memory
|
|
|
6
6
|
|
|
7
7
|
> Kirei (きれい) is a Japanese adjective that primarily means "beautiful" or "pretty." It can also be used to describe something that is "clean" or "neat."
|
|
8
8
|
|
|
9
|
-
👉 AI-generated wiki available on [DeepWiki.com](https://deepwiki.com/swiknaba/kirei)
|
|
9
|
+
👉 AI-generated wiki available on [](https://deepwiki.com/swiknaba/kirei)
|
|
10
10
|
|
|
11
11
|
## Why another Ruby framework?
|
|
12
12
|
|
|
@@ -44,7 +44,10 @@ module Cli
|
|
|
44
44
|
|
|
45
45
|
# Fifth: load configs
|
|
46
46
|
Dir[File.join(__dir__, "config", "**", "*.rb")].each do |cnf|
|
|
47
|
-
|
|
47
|
+
next if cnf.split("/").include?("initializers")
|
|
48
|
+
next if cnf.end_with?("puma.rb") # Puma config uses DSL only available when loaded by Puma
|
|
49
|
+
|
|
50
|
+
require(cnf)
|
|
48
51
|
end
|
|
49
52
|
|
|
50
53
|
class #{app_name} < Kirei::App
|
|
@@ -5,10 +5,9 @@ module Cli
|
|
|
5
5
|
module NewApp
|
|
6
6
|
module Files
|
|
7
7
|
class Routes
|
|
8
|
-
def self.call(
|
|
8
|
+
def self.call(_app_name)
|
|
9
9
|
File.write("config/routes.rb", router)
|
|
10
10
|
File.write("app/controllers/base.rb", base_controller)
|
|
11
|
-
File.write("app/controllers/health.rb", health_controller(app_name))
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
def self.router
|
|
@@ -17,16 +16,7 @@ module Cli
|
|
|
17
16
|
# frozen_string_literal: true
|
|
18
17
|
|
|
19
18
|
module Kirei::Routing
|
|
20
|
-
Router.
|
|
21
|
-
[
|
|
22
|
-
Route.new(
|
|
23
|
-
verb: Verb::GET,
|
|
24
|
-
path: "/livez",
|
|
25
|
-
controller: Controllers::Health,
|
|
26
|
-
action: "livez",
|
|
27
|
-
),
|
|
28
|
-
],
|
|
29
|
-
)
|
|
19
|
+
Router.add_health_routes!
|
|
30
20
|
end
|
|
31
21
|
RUBY
|
|
32
22
|
end
|
|
@@ -43,24 +33,6 @@ module Cli
|
|
|
43
33
|
end
|
|
44
34
|
RUBY
|
|
45
35
|
end
|
|
46
|
-
|
|
47
|
-
def self.health_controller(app_name)
|
|
48
|
-
<<~RUBY
|
|
49
|
-
# typed: strict
|
|
50
|
-
# frozen_string_literal: true
|
|
51
|
-
|
|
52
|
-
module Controllers
|
|
53
|
-
class Health < Base
|
|
54
|
-
sig { returns(T.anything) }
|
|
55
|
-
def livez
|
|
56
|
-
#{app_name}.config.logger.info("Health check")
|
|
57
|
-
#{app_name}.config.logger.info(params.inspect)
|
|
58
|
-
render(#{app_name}.version, status: 200)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
end
|
|
62
|
-
RUBY
|
|
63
|
-
end
|
|
64
36
|
end
|
|
65
37
|
end
|
|
66
38
|
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# typed: strict
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
module Kirei
|
|
5
|
+
module Controllers
|
|
6
|
+
#
|
|
7
|
+
# Built-in health check controller implementing Kubernetes API health endpoints.
|
|
8
|
+
#
|
|
9
|
+
# Provides three endpoints following the Kubernetes convention:
|
|
10
|
+
# - /livez — Liveness probe. Indicates the process is alive.
|
|
11
|
+
# - /readyz — Readiness probe. Verifies downstream dependencies (DB) are reachable.
|
|
12
|
+
# - /healthz — Deprecated alias for /livez (deprecated since Kubernetes v1.16).
|
|
13
|
+
#
|
|
14
|
+
# Reference: https://kubernetes.io/docs/reference/using-api/health-checks/
|
|
15
|
+
#
|
|
16
|
+
class Health < Kirei::Controller
|
|
17
|
+
extend T::Sig
|
|
18
|
+
|
|
19
|
+
sig { returns(Routing::RackResponseType) }
|
|
20
|
+
def livez
|
|
21
|
+
info = {
|
|
22
|
+
"status" => "ok",
|
|
23
|
+
"version" => App.version,
|
|
24
|
+
"app_name" => App.config.app_name,
|
|
25
|
+
"environment" => App.environment,
|
|
26
|
+
"req_host" => request.host,
|
|
27
|
+
"req_port" => request.port,
|
|
28
|
+
"req_ssl" => request.ssl?,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Kirei::Logging::Logger.call(
|
|
32
|
+
level: Kirei::Logging::Level::INFO,
|
|
33
|
+
label: "Health check",
|
|
34
|
+
meta: info,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
render_json(info, status: 200)
|
|
38
|
+
end
|
|
39
|
+
alias healthz livez
|
|
40
|
+
|
|
41
|
+
sig { returns(Routing::RackResponseType) }
|
|
42
|
+
def readyz
|
|
43
|
+
T.unsafe(App.raw_db_connection).execute("SELECT 1")
|
|
44
|
+
|
|
45
|
+
Kirei::Logging::Logger.call(
|
|
46
|
+
level: Kirei::Logging::Level::INFO,
|
|
47
|
+
label: "Readiness check",
|
|
48
|
+
meta: { "status" => "ok" },
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
render_json({ "status" => "ok" }, status: 200)
|
|
52
|
+
rescue Sequel::Error => e
|
|
53
|
+
Kirei::Logging::Logger.call(
|
|
54
|
+
level: Kirei::Logging::Level::ERROR,
|
|
55
|
+
label: "Readiness check failed",
|
|
56
|
+
meta: { "error" => e.message },
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
render_json({ "status" => "unavailable", "reason" => e.message }, status: 503)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/kirei/routing/base.rb
CHANGED
|
@@ -23,6 +23,7 @@ module Kirei
|
|
|
23
23
|
|
|
24
24
|
sig { params(env: RackEnvType).returns(RackResponseType) }
|
|
25
25
|
def call(env)
|
|
26
|
+
statsd_timing_tags = T.let({}, T::Hash[String, T.untyped])
|
|
26
27
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
|
27
28
|
status = 500 # we use it in the "ensure" block, so we need to define early (Sorbet doesn't like `status ||= 418`)
|
|
28
29
|
|
|
@@ -62,7 +63,7 @@ module Kirei
|
|
|
62
63
|
body.rewind # TODO: maybe don't rewind if we don't need to?
|
|
63
64
|
T.cast(res, T::Hash[String, T.untyped])
|
|
64
65
|
end
|
|
65
|
-
when Verb::HEAD, Verb::DELETE, Verb::OPTIONS
|
|
66
|
+
when Verb::HEAD, Verb::DELETE, Verb::OPTIONS
|
|
66
67
|
{}
|
|
67
68
|
else
|
|
68
69
|
T.absurd(http_verb)
|
|
@@ -90,14 +91,11 @@ module Kirei
|
|
|
90
91
|
},
|
|
91
92
|
)
|
|
92
93
|
|
|
93
|
-
statsd_timing_tags =
|
|
94
|
-
|
|
95
|
-
"route" => route.action,
|
|
96
|
-
}
|
|
97
|
-
Logging::Metric.inject_defaults(statsd_timing_tags)
|
|
94
|
+
statsd_timing_tags["controller"] = controller.name
|
|
95
|
+
statsd_timing_tags["route"] = route.action
|
|
98
96
|
|
|
99
97
|
status, headers, response_body = case http_verb
|
|
100
|
-
when Verb::HEAD, Verb::OPTIONS
|
|
98
|
+
when Verb::HEAD, Verb::OPTIONS
|
|
101
99
|
[200, {}, []]
|
|
102
100
|
when Verb::GET, Verb::POST, Verb::PUT, Verb::PATCH, Verb::DELETE
|
|
103
101
|
T.cast(
|
|
@@ -124,10 +122,35 @@ module Kirei
|
|
|
124
122
|
headers,
|
|
125
123
|
response_body,
|
|
126
124
|
]
|
|
125
|
+
rescue StandardError => e
|
|
126
|
+
status = 500
|
|
127
|
+
|
|
128
|
+
Kirei::Logging::Logger.call(
|
|
129
|
+
level: Kirei::Logging::Level::ERROR,
|
|
130
|
+
label: "Unhandled Exception",
|
|
131
|
+
meta: {
|
|
132
|
+
"error.class" => e.class.name,
|
|
133
|
+
"error.message" => e.message,
|
|
134
|
+
"error.backtrace" => e.backtrace&.first(10)&.join("\n"),
|
|
135
|
+
},
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
detail = if Kirei::App.environment == "development"
|
|
139
|
+
"#{e.class}: #{e.message}\n#{e.backtrace&.first(10)&.join("\n")}"
|
|
140
|
+
else
|
|
141
|
+
"An unexpected error occurred"
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
error = Errors::JsonApiError.new(code: "internal_server_error", detail: detail)
|
|
145
|
+
body = Oj.dump({ "errors" => [error.serialize] }, Kirei::OJ_OPTIONS)
|
|
146
|
+
response_body = [body]
|
|
147
|
+
|
|
148
|
+
[status, { "Content-Type" => "application/json; charset=utf-8" }, response_body]
|
|
127
149
|
ensure
|
|
128
150
|
stop = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
|
129
|
-
if start # early return for 404
|
|
151
|
+
if start && statsd_timing_tags # early return for 404
|
|
130
152
|
latency_in_ms = stop - start
|
|
153
|
+
Logging::Metric.inject_defaults(statsd_timing_tags)
|
|
131
154
|
App.config.metrics_backend.measure("request", latency_in_ms, tags: statsd_timing_tags)
|
|
132
155
|
|
|
133
156
|
Kirei::Logging::Logger.call(
|
data/lib/kirei/routing/router.rb
CHANGED
|
@@ -85,6 +85,18 @@ module Kirei
|
|
|
85
85
|
end
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
# must be added manually => we don't want to magically add routes for the user
|
|
89
|
+
sig { void }
|
|
90
|
+
def self.add_health_routes!
|
|
91
|
+
add_routes(
|
|
92
|
+
[
|
|
93
|
+
Route.new(verb: Verb::GET, path: "/livez", controller: Kirei::Controllers::Health, action: "livez"),
|
|
94
|
+
Route.new(verb: Verb::GET, path: "/readyz", controller: Kirei::Controllers::Health, action: "readyz"),
|
|
95
|
+
Route.new(verb: Verb::GET, path: "/healthz", controller: Kirei::Controllers::Health, action: "healthz"),
|
|
96
|
+
],
|
|
97
|
+
)
|
|
98
|
+
end
|
|
99
|
+
|
|
88
100
|
# Matches a request path against registered dynamic routes.
|
|
89
101
|
# Returns [Route, extracted_params] or nil.
|
|
90
102
|
sig do
|
data/lib/kirei/routing/verb.rb
CHANGED
data/lib/kirei/version.rb
CHANGED
data/lib/kirei.rb
CHANGED
|
@@ -67,6 +67,4 @@ loader.eager_load
|
|
|
67
67
|
|
|
68
68
|
Kirei.configure(&:itself)
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
Kirei::Logging::Logger.logger.info("Kirei v#{Kirei::VERSION} booted; YJIT enabled: #{yjit_enabled}")
|
|
70
|
+
Kirei::Logging::Logger.logger.info("Kirei v#{Kirei::VERSION} booted")
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kirei
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.10.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ludwig Reinmiedl
|
|
@@ -174,6 +174,7 @@ files:
|
|
|
174
174
|
- lib/kirei/app.rb
|
|
175
175
|
- lib/kirei/config.rb
|
|
176
176
|
- lib/kirei/controller.rb
|
|
177
|
+
- lib/kirei/controllers/health.rb
|
|
177
178
|
- lib/kirei/domain/entity.rb
|
|
178
179
|
- lib/kirei/domain/value_object.rb
|
|
179
180
|
- lib/kirei/errors/json_api_error.rb
|
|
@@ -226,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
226
227
|
- !ruby/object:Gem::Version
|
|
227
228
|
version: '0'
|
|
228
229
|
requirements: []
|
|
229
|
-
rubygems_version: 4.0.
|
|
230
|
+
rubygems_version: 4.0.6
|
|
230
231
|
specification_version: 4
|
|
231
232
|
summary: Kirei is a typed Ruby micro/REST-framework for building scalable and performant
|
|
232
233
|
microservices.
|