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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c874451fe4493ce74c1978b28cb29c90ae97c1b888b110b086e19c6bb8cd89db
4
- data.tar.gz: 13081cea051d66b4b6ecbf1eec9d4de2cc1029c22b3b7b00e5a921b4cc70c6ed
3
+ metadata.gz: cd3a6544546c69ce6ebd7eff7341a5c1de98b1507da11b9c8e295422192c2141
4
+ data.tar.gz: 2328aa5384c4f3fd04af5fc98c86abc39ecf263c95cc5b1b3566a6689cae5214
5
5
  SHA512:
6
- metadata.gz: b61dd10a594676726546302b8e8b0a1eb77d34e8ab43cec4c01c101a4b71879d34d79cde940eaf0885ffff803c080817402bdf922343b66aaf93719f879e5d0c
7
- data.tar.gz: 93e57502203a62601b70e63055bed25e12da10e33bb141d093af384522a24dfdc4c580098a1b3c330d2ff420cdd66951de5d792927a115748e1488401d30edae
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: true },
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 Websoker requests
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
@@ -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
@@ -1,5 +1,5 @@
1
1
  module StackServiceBase
2
2
  class Base
3
- VERSION = '0.0.12'
3
+ VERSION = '0.0.14'
4
4
  end
5
5
  end
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.12
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-05-23 00:00:00.000000000 Z
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