tarantool-rails 0.2.0 → 0.3.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/CHANGELOG.md +7 -0
- data/README.md +11 -1
- data/lib/generators/tarantool/install/templates/tarantool_schema.rb +1 -0
- data/lib/generators/tarantool/model/model_generator.rb +4 -2
- data/lib/tarantool/rails/configuration.rb +2 -1
- data/lib/tarantool/rails/railtie.rb +1 -0
- data/lib/tarantool/rails/schema_tasks.rb +26 -0
- data/lib/tarantool/rails/tasks/schema.rake +5 -19
- data/lib/tarantool/rails/version.rb +1 -1
- data/lib/tarantool/rails.rb +9 -3
- data/sig/tarantool/rails.rbs +59 -0
- metadata +8 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 30e777d2be6062e333e01fa5ab1e50fc2ccab417e19ae4513dddf8a5b8f2bd8f
|
|
4
|
+
data.tar.gz: 72c8fdfd334c5d3da9b62313e90e92650e7b045596d57409aff7a02e2dff8c85
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 10cd6a546bb3298f10b39a44a3fec2f79189c300e9152e0a1eaad79f9350e868b0d84caae77e77e222f2f03cc989070674cbde5b61c45a023b70cf1679636f72
|
|
7
|
+
data.tar.gz: 38f7446ec5667c71a8717e84bf4b77b2763288d8f011be423867796a982e85844651ad10296961644e8a0df7716c443b09aba827da452aa652110a1b77bed59e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0 (2026-10-18)
|
|
4
|
+
|
|
5
|
+
- `config.tarantool.instrumenter` replaces `ActiveSupport::Notifications` as the pool instrumenter, for chaining
|
|
6
|
+
tarantool-opentelemetry.
|
|
7
|
+
- Depends on `tarantool-client ~> 0.3` and `tarantool-schema ~> 0.3`; `tarantool:schema:apply` grants what the schema declares.
|
|
8
|
+
- The schema rake tasks no longer define helper methods and a constant on `Object`.
|
|
9
|
+
|
|
3
10
|
## 0.2.0 (2026-10-17)
|
|
4
11
|
|
|
5
12
|
- `tarantool:schema:dump` writes the live schema to `config/tarantool_schema.rb` (`FORCE=1` to overwrite,
|
data/README.md
CHANGED
|
@@ -67,6 +67,14 @@ can run; the first model operation then raises `Tarantool::Rails::Error`.
|
|
|
67
67
|
password).
|
|
68
68
|
- `Tarantool::Rails.pool` is one `Tarantool::Client::Pool` per process, built on first use with
|
|
69
69
|
`instrumenter: ActiveSupport::Notifications`. After `fork` the pool reopens its connections on its own.
|
|
70
|
+
`config.tarantool.instrumenter` replaces the instrumenter; the log subscriber still needs the events on
|
|
71
|
+
`ActiveSupport::Notifications`, so chain it:
|
|
72
|
+
|
|
73
|
+
```ruby
|
|
74
|
+
# config/initializers/tarantool.rb
|
|
75
|
+
Rails.application.config.tarantool.instrumenter =
|
|
76
|
+
Tarantool::OpenTelemetry::Instrumenter.new(instrumenter: ActiveSupport::Notifications)
|
|
77
|
+
```
|
|
70
78
|
- `Tarantool::Rails.storage` is a `Storage::Box` (or `Storage::Crud`) over the pool, and
|
|
71
79
|
`Tarantool::Model.default_storage` is set so every model without a storage of its own uses it. Nothing
|
|
72
80
|
connects until a model is used.
|
|
@@ -118,7 +126,7 @@ end
|
|
|
118
126
|
| Task | |
|
|
119
127
|
|---|---|
|
|
120
128
|
| `rails tarantool:schema:plan` | prints what `apply` would create; drift raises `MismatchError` with the diff |
|
|
121
|
-
| `rails tarantool:schema:apply` | creates the missing spaces and
|
|
129
|
+
| `rails tarantool:schema:apply` | creates the missing spaces, indexes and grants and prints them; never drops |
|
|
122
130
|
| `rails tarantool:schema:check` | for CI: exits 1 and prints `pending: ...` when anything would be created, 0 when live equals declared |
|
|
123
131
|
| `rails tarantool:schema:dump` | writes the live schema to `config/tarantool_schema.rb` for bootstrapping; refuses to overwrite unless `FORCE=1`; `dump[users,codes]` limits the spaces |
|
|
124
132
|
|
|
@@ -201,6 +209,8 @@ gem must be in the Gemfile.
|
|
|
201
209
|
`Tarantool::Rails::Configuration`, `Tarantool::Rails::LogSubscriber`, `Tarantool::Rails::Error`
|
|
202
210
|
(descends from `Tarantool::Error`), the rake tasks and the generators.
|
|
203
211
|
|
|
212
|
+
RBS signatures for this API ship with the gem in `sig/`.
|
|
213
|
+
|
|
204
214
|
Everything else, including anything tagged `@api private` in its source comment, is an implementation detail
|
|
205
215
|
and may change in any release.
|
|
206
216
|
|
|
@@ -5,4 +5,5 @@ Tarantool::Rails.schema = Tarantool::Schema::Definition.new do
|
|
|
5
5
|
# ensure_space :users,
|
|
6
6
|
# format: [{ name: :id, type: :unsigned }, { name: :email, type: :string }],
|
|
7
7
|
# indexes: [{ name: :primary, parts: [:id], sequence: true }, { name: :email, parts: [:email] }]
|
|
8
|
+
# grant :app, %i[read write], on: :users
|
|
8
9
|
end
|
|
@@ -22,6 +22,8 @@ module Tarantool
|
|
|
22
22
|
}.freeze
|
|
23
23
|
ID = Field.new(name: 'id', attribute_type: ':integer', field_type: 'unsigned', nullable: false)
|
|
24
24
|
SCHEMA_PATH = 'config/tarantool_schema.rb'
|
|
25
|
+
SCHEMA_END = /^end\s*\z/
|
|
26
|
+
LINE_START = /^/
|
|
25
27
|
|
|
26
28
|
source_root File.expand_path('templates', __dir__)
|
|
27
29
|
|
|
@@ -40,7 +42,7 @@ module Tarantool
|
|
|
40
42
|
def add_space_to_schema
|
|
41
43
|
return if options[:skip_schema] || !File.exist?(File.join(destination_root, SCHEMA_PATH))
|
|
42
44
|
|
|
43
|
-
inject_into_file SCHEMA_PATH, space_declaration, before:
|
|
45
|
+
inject_into_file SCHEMA_PATH, space_declaration, before: SCHEMA_END
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
private
|
|
@@ -70,7 +72,7 @@ module Tarantool
|
|
|
70
72
|
' ],', ' indexes: [',
|
|
71
73
|
" { name: :primary, parts: [:#{model_fields.first.name}]#{sequence} }", ' ]']
|
|
72
74
|
|
|
73
|
-
"\n#{lines.join("\n").gsub(
|
|
75
|
+
"\n#{lines.join("\n").gsub(LINE_START, ' ')}\n"
|
|
74
76
|
end
|
|
75
77
|
end
|
|
76
78
|
end
|
|
@@ -17,7 +17,7 @@ module Tarantool
|
|
|
17
17
|
def filtered(key, value)
|
|
18
18
|
case key
|
|
19
19
|
when :client_options then value.key?(:password) ? value.merge(password: '[FILTERED]') : value
|
|
20
|
-
when :admin_uri then value&.sub(
|
|
20
|
+
when :admin_uri then value&.sub(Configuration::URI_PASSWORD, ':[FILTERED]@')
|
|
21
21
|
else value
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -30,6 +30,7 @@ module Tarantool
|
|
|
30
30
|
KEYS = (CLIENT_KEYS + %i[addresses address read write storage crud admin_uri]).freeze
|
|
31
31
|
CRUD_KEYS = %i[primary_index read write timeout_margin].freeze
|
|
32
32
|
STORAGES = %i[box crud].freeze
|
|
33
|
+
URI_PASSWORD = %r{:[^:@/]*@}
|
|
33
34
|
|
|
34
35
|
class << self
|
|
35
36
|
def from_hash(hash)
|
|
@@ -10,6 +10,7 @@ module Tarantool
|
|
|
10
10
|
# A missing config/tarantool.yml is not an error at boot: the install generator has to be able to run.
|
|
11
11
|
initializer 'tarantool.configuration' do |app|
|
|
12
12
|
Tarantool::Rails.schema_path = app.config.tarantool.schema_path || app.root.join('config/tarantool_schema.rb')
|
|
13
|
+
Tarantool::Rails.instrumenter = app.config.tarantool.instrumenter
|
|
13
14
|
next unless app.root.join('config/tarantool.yml').exist?
|
|
14
15
|
|
|
15
16
|
section = app.config_for(:tarantool)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Tarantool
|
|
4
|
+
module Rails
|
|
5
|
+
# Helpers behind the tarantool:schema rake tasks.
|
|
6
|
+
# @api private
|
|
7
|
+
module SchemaTasks
|
|
8
|
+
# Task arguments are one String: rails "tarantool:schema:apply[add_field]", "tarantool:schema:dump[users,codes]".
|
|
9
|
+
NAME_SEPARATOR = /[\s,]+/
|
|
10
|
+
|
|
11
|
+
module_function
|
|
12
|
+
|
|
13
|
+
def names(argument) = argument.to_s.split(NAME_SEPARATOR).reject(&:empty?)
|
|
14
|
+
|
|
15
|
+
def dump(path, only)
|
|
16
|
+
abort "#{path} exists; set FORCE=1 to overwrite" if File.exist?(path) && ENV['FORCE'].to_s.empty?
|
|
17
|
+
|
|
18
|
+
definition = Tarantool::Rails.admin_client do |client|
|
|
19
|
+
Tarantool::Schema::Definition.from_live(client, only: only.empty? ? nil : only)
|
|
20
|
+
end
|
|
21
|
+
File.write(path, "# frozen_string_literal: true\n\nTarantool::Rails.schema = #{definition.to_ruby}")
|
|
22
|
+
puts path
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -1,37 +1,22 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
# Task arguments are one String: rails "tarantool:schema:apply[add_field]", "tarantool:schema:dump[users,codes]".
|
|
4
|
-
TARANTOOL_SCHEMA_NAME_SEPARATOR = /[\s,]+/
|
|
5
|
-
|
|
6
|
-
def tarantool_schema_names(argument) = argument.to_s.split(TARANTOOL_SCHEMA_NAME_SEPARATOR).reject(&:empty?)
|
|
7
|
-
|
|
8
|
-
def tarantool_schema_dump(path, only)
|
|
9
|
-
abort "#{path} exists; set FORCE=1 to overwrite" if File.exist?(path) && ENV['FORCE'].to_s.empty?
|
|
10
|
-
|
|
11
|
-
definition = Tarantool::Rails.admin_client do |client|
|
|
12
|
-
Tarantool::Schema::Definition.from_live(client, only: only.empty? ? nil : only)
|
|
13
|
-
end
|
|
14
|
-
File.write(path, "# frozen_string_literal: true\n\nTarantool::Rails.schema = #{definition.to_ruby}")
|
|
15
|
-
puts path
|
|
16
|
-
end
|
|
17
|
-
|
|
18
3
|
namespace :tarantool do
|
|
19
4
|
namespace :schema do
|
|
20
5
|
desc 'Print what tarantool:schema:apply would create; fail on drift'
|
|
21
6
|
task :plan, [:alter] => :environment do |_task, args|
|
|
22
|
-
alter =
|
|
7
|
+
alter = Tarantool::Rails::SchemaTasks.names(args[:alter]).map(&:to_sym)
|
|
23
8
|
Tarantool::Rails.admin_client { |client| puts Tarantool::Rails.schema.plan(client, alter:) }
|
|
24
9
|
end
|
|
25
10
|
|
|
26
11
|
desc 'Create missing Tarantool spaces and indexes; fail on drift'
|
|
27
12
|
task :apply, [:alter] => :environment do |_task, args|
|
|
28
|
-
alter =
|
|
13
|
+
alter = Tarantool::Rails::SchemaTasks.names(args[:alter]).map(&:to_sym)
|
|
29
14
|
Tarantool::Rails.admin_client { |client| puts Tarantool::Rails.schema.apply(client, alter:) }
|
|
30
15
|
end
|
|
31
16
|
|
|
32
17
|
desc 'Fail unless the live schema equals the declaration, for CI'
|
|
33
18
|
task :check, [:alter] => :environment do |_task, args|
|
|
34
|
-
alter =
|
|
19
|
+
alter = Tarantool::Rails::SchemaTasks.names(args[:alter]).map(&:to_sym)
|
|
35
20
|
pending = Tarantool::Rails.admin_client { |client| Tarantool::Rails.schema.plan(client, alter:) }
|
|
36
21
|
next if pending.empty?
|
|
37
22
|
|
|
@@ -41,7 +26,8 @@ namespace :tarantool do
|
|
|
41
26
|
|
|
42
27
|
desc 'Write the live schema to config/tarantool_schema.rb (FORCE=1 to overwrite; spaces as [users,codes])'
|
|
43
28
|
task :dump, [:only] => :environment do |_task, args|
|
|
44
|
-
|
|
29
|
+
Tarantool::Rails::SchemaTasks.dump(Tarantool::Rails.schema_path.to_s,
|
|
30
|
+
Tarantool::Rails::SchemaTasks.names(args[:only]))
|
|
45
31
|
end
|
|
46
32
|
end
|
|
47
33
|
end
|
data/lib/tarantool/rails.rb
CHANGED
|
@@ -10,6 +10,7 @@ require_relative 'rails/errors'
|
|
|
10
10
|
require_relative 'rails/configuration'
|
|
11
11
|
require_relative 'rails/log_subscriber'
|
|
12
12
|
require_relative 'rails/controller_runtime'
|
|
13
|
+
require_relative 'rails/schema_tasks'
|
|
13
14
|
require_relative 'rails/railtie' if defined?(Rails::Railtie)
|
|
14
15
|
|
|
15
16
|
module Tarantool
|
|
@@ -21,7 +22,13 @@ module Tarantool
|
|
|
21
22
|
|
|
22
23
|
class << self
|
|
23
24
|
attr_accessor :config, :schema_path
|
|
24
|
-
attr_writer :schema
|
|
25
|
+
attr_writer :schema, :instrumenter
|
|
26
|
+
|
|
27
|
+
# What the pool reports requests to; the log subscriber listens to ActiveSupport::Notifications, so an
|
|
28
|
+
# instrumenter of your own should chain it (tarantool-opentelemetry's does with `instrumenter:`).
|
|
29
|
+
def instrumenter
|
|
30
|
+
@instrumenter || ActiveSupport::Notifications
|
|
31
|
+
end
|
|
25
32
|
|
|
26
33
|
def pool
|
|
27
34
|
LOCK.synchronize { @pool ||= build_pool }
|
|
@@ -69,8 +76,7 @@ module Tarantool
|
|
|
69
76
|
end
|
|
70
77
|
|
|
71
78
|
def build_pool
|
|
72
|
-
Tarantool::Client::Pool.new(configured.addresses, **configured.client_options,
|
|
73
|
-
instrumenter: ActiveSupport::Notifications)
|
|
79
|
+
Tarantool::Client::Pool.new(configured.addresses, **configured.client_options, instrumenter:)
|
|
74
80
|
end
|
|
75
81
|
|
|
76
82
|
def build_storage
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module Tarantool
|
|
2
|
+
# Rails integration: configuration from config/tarantool.yml, one Pool per process, models on it, log lines,
|
|
3
|
+
# schema rake tasks and generators.
|
|
4
|
+
module Rails
|
|
5
|
+
VERSION: String
|
|
6
|
+
|
|
7
|
+
def self.config: () -> Configuration?
|
|
8
|
+
def self.config=: (Configuration? config) -> void
|
|
9
|
+
def self.schema_path: () -> (String | Pathname)?
|
|
10
|
+
def self.schema_path=: ((String | Pathname)? path) -> void
|
|
11
|
+
# Loaded from schema_path on first use; the file assigns it.
|
|
12
|
+
def self.schema: () -> Tarantool::Schema::Definition
|
|
13
|
+
def self.schema=: (Tarantool::Schema::Definition? schema) -> void
|
|
14
|
+
# ActiveSupport::Notifications unless configured.
|
|
15
|
+
def self.instrumenter: () -> Tarantool::Client::_Instrumenter
|
|
16
|
+
def self.instrumenter=: (Tarantool::Client::_Instrumenter? instrumenter) -> void
|
|
17
|
+
def self.pool: () -> Tarantool::Client::Pool
|
|
18
|
+
def self.storage: () -> (Tarantool::Model::Storage::Box | Tarantool::Model::Storage::Crud)
|
|
19
|
+
def self.admin_client: [T] () { (Tarantool::Client client) -> T } -> T
|
|
20
|
+
def self.use_default_storage!: () -> void
|
|
21
|
+
def self.disconnect!: () -> void
|
|
22
|
+
|
|
23
|
+
class Error < Tarantool::Error
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# One environment section of config/tarantool.yml; inspect and to_s hide the password.
|
|
27
|
+
class Configuration < Data
|
|
28
|
+
attr_reader addresses: Array[String]
|
|
29
|
+
attr_reader client_options: Hash[Symbol, untyped]
|
|
30
|
+
attr_reader storage: :box | :crud
|
|
31
|
+
attr_reader read: Hash[Symbol, untyped]
|
|
32
|
+
attr_reader write: Hash[Symbol, untyped]
|
|
33
|
+
attr_reader crud: Hash[Symbol, untyped]
|
|
34
|
+
attr_reader admin_uri: String?
|
|
35
|
+
|
|
36
|
+
# The Hash config_for returns (an ActiveSupport::OrderedOptions is a Hash); unknown keys raise ArgumentError.
|
|
37
|
+
def self.from_hash: (Hash[Symbol | String, untyped] hash) -> Configuration
|
|
38
|
+
def inspect: () -> String
|
|
39
|
+
def to_s: () -> String
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# ActiveRecord-style log lines for the client's events (an ActiveSupport::LogSubscriber); the time spent in
|
|
43
|
+
# requests is accumulated per thread for the controller log.
|
|
44
|
+
class LogSubscriber
|
|
45
|
+
def self.runtime: () -> Float
|
|
46
|
+
def self.runtime=: (Float value) -> void
|
|
47
|
+
def self.reset_runtime: () -> Float
|
|
48
|
+
|
|
49
|
+
# Each takes an ActiveSupport::Notifications::Event.
|
|
50
|
+
def request: (untyped event) -> void
|
|
51
|
+
def disconnect: (untyped event) -> void
|
|
52
|
+
def reconnect: (untyped event) -> void
|
|
53
|
+
def reconnect_failed: (untyped event) -> void
|
|
54
|
+
def fork: (untyped event) -> void
|
|
55
|
+
def role_change: (untyped event) -> void
|
|
56
|
+
def shutdown: (untyped event) -> void
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tarantool-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Starlexxx
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: railties
|
|
@@ -36,14 +36,14 @@ dependencies:
|
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0.
|
|
39
|
+
version: '0.3'
|
|
40
40
|
type: :runtime
|
|
41
41
|
prerelease: false
|
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0.
|
|
46
|
+
version: '0.3'
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: tarantool-model
|
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -64,14 +64,14 @@ dependencies:
|
|
|
64
64
|
requirements:
|
|
65
65
|
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '0.
|
|
67
|
+
version: '0.3'
|
|
68
68
|
type: :runtime
|
|
69
69
|
prerelease: false
|
|
70
70
|
version_requirements: !ruby/object:Gem::Requirement
|
|
71
71
|
requirements:
|
|
72
72
|
- - "~>"
|
|
73
73
|
- !ruby/object:Gem::Version
|
|
74
|
-
version: '0.
|
|
74
|
+
version: '0.3'
|
|
75
75
|
description: config/tarantool.yml per environment, one connection pool per process,
|
|
76
76
|
models on it without an initializer, ActiveRecord-style log lines, schema rake tasks
|
|
77
77
|
and generators.
|
|
@@ -95,8 +95,10 @@ files:
|
|
|
95
95
|
- lib/tarantool/rails/errors.rb
|
|
96
96
|
- lib/tarantool/rails/log_subscriber.rb
|
|
97
97
|
- lib/tarantool/rails/railtie.rb
|
|
98
|
+
- lib/tarantool/rails/schema_tasks.rb
|
|
98
99
|
- lib/tarantool/rails/tasks/schema.rake
|
|
99
100
|
- lib/tarantool/rails/version.rb
|
|
101
|
+
- sig/tarantool/rails.rbs
|
|
100
102
|
homepage: https://github.com/Starlexxx/tarantool-ruby
|
|
101
103
|
licenses:
|
|
102
104
|
- MIT
|