stack-service-base 0.0.12 → 0.0.14
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/lib/stack-service-base/fiber_pool.rb +99 -0
- data/lib/stack-service-base/open_telemetry.rb +5 -2
- data/lib/stack-service-base/rack_helpers.rb +10 -0
- data/lib/stack-service-base.rb +3 -0
- data/lib/version.rb +1 -1
- 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: cd3a6544546c69ce6ebd7eff7341a5c1de98b1507da11b9c8e295422192c2141
|
4
|
+
data.tar.gz: 2328aa5384c4f3fd04af5fc98c86abc39ecf263c95cc5b1b3566a6689cae5214
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3738ed3de0e7a67c9bcc96bac1032b3d9f3e3c795468073f6056a00cfa56f1b83d4eb07ef5a3f5cc35f80304c2cbf18c45ca42b3502ca6677a9f876e6765b479
|
7
|
+
data.tar.gz: 17d3f71a9195f62b5d40870ae38d278e6306d0a58c5f843b98547bc886ac1b5d2a30c5550bac8939b82164d1b410fd808f006484d128143dda51e97d6994f3a0
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
require 'async/semaphore'
|
3
|
+
# $stdout.sync = true
|
4
|
+
|
5
|
+
class FiberConnectionPool < Sequel::ConnectionPool
|
6
|
+
VALIDATION_TIMEOUT = 20
|
7
|
+
POOL_SIZE = 10
|
8
|
+
|
9
|
+
def log(msg)
|
10
|
+
return if defined? PERFORMANCE
|
11
|
+
$stdout.puts "F:#{Fiber.current.__id__} : T:#{Thread.current.__id__} : A:#{self.__id__} : #{msg}"
|
12
|
+
# LOGGER.debug :fiber_pool, msg
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(db, opts = OPTS)
|
16
|
+
super
|
17
|
+
@allocator = ->() {
|
18
|
+
make_new(:default).tap { |conn|
|
19
|
+
log "new connection (fiber pool) #{conn}"
|
20
|
+
}
|
21
|
+
}
|
22
|
+
@stock = []
|
23
|
+
@acquired = {}
|
24
|
+
@sp = Async::Semaphore.new opts[:max_connections] || POOL_SIZE
|
25
|
+
end
|
26
|
+
|
27
|
+
def is_valid_connection?(conn)
|
28
|
+
sql = valid_connection_sql
|
29
|
+
log_connection_execute(conn, sql)
|
30
|
+
true
|
31
|
+
rescue =>e_
|
32
|
+
conn.close rescue
|
33
|
+
false
|
34
|
+
end
|
35
|
+
|
36
|
+
def hold(_server = nil)
|
37
|
+
return yield @acquired[Fiber.current] if @acquired[Fiber.current] # protect from recursion
|
38
|
+
log "hold in (fiber pool: #{__id__}) #{@stock.map{_1.__id__}}"
|
39
|
+
fiber = Fiber.current
|
40
|
+
try_count = 2
|
41
|
+
|
42
|
+
@sp.acquire do
|
43
|
+
until @acquired[fiber] &&
|
44
|
+
( @acquired[fiber].instance_eval { @last_use_.nil? || (Time.now - @last_use_).to_i < VALIDATION_TIMEOUT } ||
|
45
|
+
is_valid_connection?(@acquired[fiber]) )
|
46
|
+
|
47
|
+
@acquired[fiber] = @stock.shift || @allocator.call
|
48
|
+
end
|
49
|
+
|
50
|
+
@acquired[fiber].instance_eval { @last_use_ = Time.now }
|
51
|
+
yield @acquired[fiber]
|
52
|
+
|
53
|
+
rescue Sequel::DatabaseDisconnectError => e
|
54
|
+
log "remove connection (fiber pool) retry(#{try_count})"
|
55
|
+
@acquired.delete(fiber)
|
56
|
+
(try_count -=1) < 0 ? raise : retry
|
57
|
+
|
58
|
+
rescue =>e
|
59
|
+
$stdout.puts e.message
|
60
|
+
$stdout.puts e.backtrace[0..10].join "\n"
|
61
|
+
log 'remove connection (fiber pool) give up'
|
62
|
+
@acquired.delete(fiber)
|
63
|
+
raise
|
64
|
+
ensure
|
65
|
+
@stock.push @acquired.delete(fiber) if @acquired[fiber]
|
66
|
+
log "hold out (fiber pool: #{__id__}) #{@stock.map{_1.__id__}}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def size = @acquired.size
|
71
|
+
def max_size = @sp.limit
|
72
|
+
# def preconnect(_concurrent = false) = :unimplemented
|
73
|
+
def disconnect(symbol)
|
74
|
+
until @stock.empty?
|
75
|
+
log 'disconnect connection (fiber pool)'
|
76
|
+
@stock.shift.close
|
77
|
+
end
|
78
|
+
end
|
79
|
+
# def servers = []
|
80
|
+
def pool_type = :fiber # :threaded
|
81
|
+
def sync = yield
|
82
|
+
end
|
83
|
+
|
84
|
+
# Override Sequel::Database to use FiberConnectionPool by default.
|
85
|
+
Sequel::Database.prepend(Module.new do
|
86
|
+
def connection_pool_default_options = { pool_class: FiberConnectionPool }
|
87
|
+
end)
|
88
|
+
|
89
|
+
require 'sequel/adapters/postgres'
|
90
|
+
|
91
|
+
class Sequel::Postgres::Adapter
|
92
|
+
def execute_query(sql, args)
|
93
|
+
$stdout.puts "F:#{Fiber.current.__id__} : T:#{Thread.current.__id__} : A:#{self.__id__} : #{sql[0..60]}" unless defined? PERFORMANCE
|
94
|
+
@db.log_connection_yield(sql, self, args){args ? async_exec_params(sql, args) : async_exec(sql)}
|
95
|
+
rescue => e
|
96
|
+
$stdout.puts e.message
|
97
|
+
raise
|
98
|
+
end
|
99
|
+
end
|
@@ -60,10 +60,13 @@ def otel_initialize
|
|
60
60
|
|
61
61
|
OpenTelemetry::SDK.configure do |c|
|
62
62
|
OpenTelemetry::Instrumentation::Rack
|
63
|
+
# OpenTelemetry::Instrumentation::Rack::Middlewares::TracerMiddleware
|
64
|
+
# Rack::Builder
|
65
|
+
OpenTelemetry::Instrumentation::Sinatra
|
63
66
|
c.use_all({
|
64
|
-
'OpenTelemetry::Instrumentation::Sinatra' => { install_rack:
|
67
|
+
'OpenTelemetry::Instrumentation::Sinatra' => { install_rack: false }, # instlled by stack-service-base.rb#24 (use *OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.middleware_args)
|
65
68
|
'OpenTelemetry::Instrumentation::Rack' => {
|
66
|
-
use_rack_events: false, # TODO: doesnt work with
|
69
|
+
use_rack_events: false, # TODO: doesnt work with Websoket requests
|
67
70
|
# /home/user/.rbenv/versions/3.3.1/lib/ruby/gems/3.3.0/gems/opentelemetry-instrumentation-rack-0.26.0/lib/opentelemetry/instrumentation/rack/instrumentation.rb#43
|
68
71
|
url_quantization: ->(path, env) { "HTTP #{env['REQUEST_METHOD']} #{path}" },
|
69
72
|
untraced_requests: ->(env) { env['HTTP_UPGRADE'] == 'websocket' }
|
@@ -46,6 +46,16 @@ module RackHelpers
|
|
46
46
|
|
47
47
|
#
|
48
48
|
|
49
|
+
Rack.define_middleware :OTELTraceFullRequest do |env, app, opts|
|
50
|
+
request_headers = env.select { |k, _| k.start_with? 'HTTP_' }
|
51
|
+
request_body = env['rack.input'].read
|
52
|
+
|
53
|
+
response_code, response_headers, response_body = app.call(env)
|
54
|
+
response_body = response_body.read if response_body.respond_to? :read
|
55
|
+
otl_span( :Request, {request_headers: , request_body:, response_code:, response_headers: , response_body: }) {}
|
56
|
+
[response_code, response_headers, response_body]
|
57
|
+
end
|
58
|
+
|
49
59
|
Rack.define_middleware :OTELTraceInfo do |env, app, opts|
|
50
60
|
status, headers, body = app.call env
|
51
61
|
if status.to_i >= 500
|
data/lib/stack-service-base.rb
CHANGED
@@ -21,6 +21,7 @@ module StackServiceBase
|
|
21
21
|
|
22
22
|
if OTEL_ENABLED
|
23
23
|
otel_initialize
|
24
|
+
use *OpenTelemetry::Instrumentation::Rack::Instrumentation.instance.middleware_args
|
24
25
|
end
|
25
26
|
|
26
27
|
if defined? Sequel
|
@@ -47,6 +48,8 @@ module StackServiceBase
|
|
47
48
|
|
48
49
|
Sequel.singleton_class.prepend(mod)
|
49
50
|
# ---
|
51
|
+
#
|
52
|
+
require_relative 'stack-service-base/fiber_pool'
|
50
53
|
end
|
51
54
|
end
|
52
55
|
end
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stack-service-base
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ''
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: async
|
@@ -171,6 +171,7 @@ extensions: []
|
|
171
171
|
extra_rdoc_files: []
|
172
172
|
files:
|
173
173
|
- lib/stack-service-base.rb
|
174
|
+
- lib/stack-service-base/fiber_pool.rb
|
174
175
|
- lib/stack-service-base/logging.rb
|
175
176
|
- lib/stack-service-base/open_telemetry.rb
|
176
177
|
- lib/stack-service-base/prometheus.rb
|