beamer-rails 0.1.0.beta4-arm64-linux-musl
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 +7 -0
- data/LICENSE.txt +21 -0
- data/exe/arm64-linux-musl/beamer +0 -0
- data/exe/arm64-linux-musl/beamer.so +0 -0
- data/exe/beamer +13 -0
- data/lib/beamer/connection_adapter.rb +91 -0
- data/lib/beamer/railtie.rb +26 -0
- data/lib/beamer/tenanted_database_adapter.rb +23 -0
- data/lib/beamer/version.rb +16 -0
- data/lib/beamer-rails.rb +1 -0
- data/lib/beamer.rb +98 -0
- metadata +82 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: a7c6f838b119ac53586a0528b8b8fa6280163eaecbb801599e12ad00e0a6a6a3
|
|
4
|
+
data.tar.gz: 99c43286103dbbcb3560ecf03920e1f7004d64c329b1b0e2fe1f6cfc64d7fffd
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 8c9659fb35a6bfeed36293c726e1c31fa1af8cfad5cb5c311353262fc1e101ca7904640d80f6ef0ddff305c678acbab2501b02188408e0a541c2c16a23cc36e0
|
|
7
|
+
data.tar.gz: 30b49e1ccd9e2b272f3008b0ac15c878271127f206a1e9dfaeb3d1d078cb9ba01e754ac16999244f3e8ea09d9121667849c61c16abfc3977f1a84811970023e2
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Kevin McConnell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
Binary file
|
|
Binary file
|
data/exe/beamer
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative "../lib/beamer"
|
|
5
|
+
|
|
6
|
+
executable = File.join(Beamer.exe_dir, "beamer")
|
|
7
|
+
|
|
8
|
+
if File.exist?(executable)
|
|
9
|
+
exec(executable, *ARGV)
|
|
10
|
+
else
|
|
11
|
+
STDERR.puts("ERROR: Unsupported platform: #{Beamer.platform}")
|
|
12
|
+
exit 1
|
|
13
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_record/connection_adapters/sqlite3_adapter"
|
|
4
|
+
|
|
5
|
+
# ActiveRecord database adapter for Beamer-replicated SQLite databases.
|
|
6
|
+
#
|
|
7
|
+
# This adapter extends the standard SQLite3Adapter to automatically configure
|
|
8
|
+
# databases for Beamer replication. It loads the Beamer VFS extension and
|
|
9
|
+
# ensures the database connection uses it.
|
|
10
|
+
#
|
|
11
|
+
# @example database.yml configuration
|
|
12
|
+
# production:
|
|
13
|
+
# adapter: beamer
|
|
14
|
+
# database: storage/production.sqlite3
|
|
15
|
+
#
|
|
16
|
+
# @api private
|
|
17
|
+
class Beamer::ConnectionAdapter < ActiveRecord::ConnectionAdapters::SQLite3Adapter
|
|
18
|
+
ADAPTER_NAME = "Beamer"
|
|
19
|
+
BOOLEAN = ActiveRecord::Type::Boolean.new
|
|
20
|
+
|
|
21
|
+
# Initialize a new Beamer database connection.
|
|
22
|
+
#
|
|
23
|
+
# This loads the Beamer VFS extension, validates that the database is not
|
|
24
|
+
# in-memory, and configures the connection to use the Beamer VFS.
|
|
25
|
+
#
|
|
26
|
+
# @raise [Beamer::UnsupportedDatabaseType] if attempting to use an in-memory database
|
|
27
|
+
# @raise [Beamer::UnsupportedPlatform] if the Beamer extension is not available
|
|
28
|
+
def initialize(...)
|
|
29
|
+
Beamer.load
|
|
30
|
+
|
|
31
|
+
super
|
|
32
|
+
|
|
33
|
+
if @memory_database
|
|
34
|
+
raise Beamer::UnsupportedDatabaseType, "Beamer isn't compatible with in-memory databases"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
configure_beamer(@connection_parameters)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def beamer_primary?
|
|
41
|
+
BOOLEAN.cast(execute_pragma("beamer_is_primary")) if beamer_primary
|
|
42
|
+
rescue ActiveRecord::StatementInvalid
|
|
43
|
+
nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def beamer_primary
|
|
47
|
+
execute_pragma("beamer_primary").presence
|
|
48
|
+
rescue ActiveRecord::StatementInvalid
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def beamer_last_txn
|
|
53
|
+
execute_pragma("beamer_last_txn").presence
|
|
54
|
+
rescue ActiveRecord::StatementInvalid
|
|
55
|
+
nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def beamer_zone
|
|
59
|
+
execute_pragma("beamer_zone").presence
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def beamer_zone=(desired_zone)
|
|
63
|
+
execute_pragma("beamer_zone = #{quote(desired_zone)}").tap do |new_zone|
|
|
64
|
+
if new_zone != desired_zone
|
|
65
|
+
raise Beamer::ZoneChangeError, "Failed to set Beamer zone to #{desired_zone.inspect}"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
def configure_beamer(config)
|
|
72
|
+
inject_vfs(config)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def inject_vfs(config)
|
|
76
|
+
if config[:database].blank?
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
database, query_string = config[:database].split("?", 2)
|
|
80
|
+
attributes = query_string ? CGI.parse(query_string) : {}
|
|
81
|
+
|
|
82
|
+
attributes["vfs"] = "beamer"
|
|
83
|
+
database = "file:#{database}" unless database.start_with?("file:")
|
|
84
|
+
|
|
85
|
+
config[:database] = "#{database}?#{URI.encode_www_form(attributes)}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def execute_pragma(pragma)
|
|
89
|
+
execute("PRAGMA #{pragma}").first&.values&.first
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Rails integration for Beamer.
|
|
4
|
+
#
|
|
5
|
+
# This Railtie automatically registers the Beamer database adapter with ActiveRecord
|
|
6
|
+
# during Rails initialization, allowing you to use `adapter: beamer` in database.yml.
|
|
7
|
+
#
|
|
8
|
+
# @example database.yml configuration
|
|
9
|
+
# production:
|
|
10
|
+
# adapter: beamer
|
|
11
|
+
# database: storage/production.sqlite3
|
|
12
|
+
#
|
|
13
|
+
# @api private
|
|
14
|
+
class Beamer::Railtie < ::Rails::Railtie
|
|
15
|
+
# Register the Beamer adapter before Rails configuration is loaded.
|
|
16
|
+
# This ensures the adapter is available when database.yml is parsed.
|
|
17
|
+
config.before_configuration do
|
|
18
|
+
ActiveRecord::ConnectionAdapters.register("beamer", "Beamer::ConnectionAdapter", "beamer/connection_adapter")
|
|
19
|
+
ActiveRecord::Tasks::DatabaseTasks.register_task(/beamer/, "ActiveRecord::Tasks::SQLiteDatabaseTasks")
|
|
20
|
+
|
|
21
|
+
if defined?(ActiveRecord::Tenanted)
|
|
22
|
+
require "beamer/tenanted_database_adapter"
|
|
23
|
+
ActiveRecord::Tenanted::DatabaseAdapter.register("beamer", "Beamer::TenantedDatabaseAdapter")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_record/tenanted/database_adapters/sqlite"
|
|
4
|
+
|
|
5
|
+
# Database adapter for ActiveRecord::Tenanted that enables Beamer replication
|
|
6
|
+
# for tenanted databases.
|
|
7
|
+
#
|
|
8
|
+
# This adapter extends the standard SQLite tenanted adapter with Beamer's VFS,
|
|
9
|
+
# allowing each tenant database to have its own replication state and benefit
|
|
10
|
+
# from Beamer's replication capabilities.
|
|
11
|
+
#
|
|
12
|
+
# The adapter is automatically registered when ActiveRecord::Tenanted is detected
|
|
13
|
+
# during Rails initialization (see Beamer::Railtie).
|
|
14
|
+
#
|
|
15
|
+
# @example Creating a tenanted database with Beamer
|
|
16
|
+
# # With adapter: beamer in database.yml
|
|
17
|
+
# ActiveRecord::Tenanted.create_tenant("tenant-1")
|
|
18
|
+
# # Creates a database using Beamer VFS with its own .beamer directory
|
|
19
|
+
#
|
|
20
|
+
# @see https://github.com/basecamp/activerecord-tenanted
|
|
21
|
+
# @api private
|
|
22
|
+
class Beamer::TenantedDatabaseAdapter < ActiveRecord::Tenanted::DatabaseAdapters::SQLite
|
|
23
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Beamer
|
|
4
|
+
VERSION = "0.1.0.beta4"
|
|
5
|
+
|
|
6
|
+
NATIVE_PLATFORMS = {
|
|
7
|
+
"arm-linux-gnu" => "../../release/arm-linux-gnu",
|
|
8
|
+
"arm-linux-musl" => "../../release/arm-linux-musl",
|
|
9
|
+
"arm64-darwin" => "../../release/arm64-darwin",
|
|
10
|
+
"arm64-linux-gnu" => "../../release/aarch64-linux-gnu",
|
|
11
|
+
"arm64-linux-musl" => "../../release/aarch64-linux-musl",
|
|
12
|
+
"x86_64-darwin" => "../../release/x86_64-darwin",
|
|
13
|
+
"x86_64-linux-gnu" => "../../release/x86_64-linux-gnu",
|
|
14
|
+
"x86_64-linux-musl" => "../../release/x86_64-linux-musl"
|
|
15
|
+
}
|
|
16
|
+
end
|
data/lib/beamer-rails.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require_relative "./beamer"
|
data/lib/beamer.rb
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "sqlite3"
|
|
4
|
+
require "rubygems"
|
|
5
|
+
|
|
6
|
+
require_relative "beamer/version"
|
|
7
|
+
require_relative "beamer/railtie" if defined?(Rails)
|
|
8
|
+
|
|
9
|
+
module Beamer
|
|
10
|
+
GEM_NAME = "beamer-rails"
|
|
11
|
+
|
|
12
|
+
autoload :ConnectionAdapter, "beamer/connection_adapter"
|
|
13
|
+
|
|
14
|
+
# Base exception class for the library.
|
|
15
|
+
class Error < StandardError; end
|
|
16
|
+
|
|
17
|
+
# Raised when the SQLite extension isn't packaged for the current OS, processor and ABI.
|
|
18
|
+
class UnsupportedPlatform < Error; end
|
|
19
|
+
|
|
20
|
+
# Raised when attempting to use Beamer to replicate an unsupported type of database.
|
|
21
|
+
class UnsupportedDatabaseType < Error; end
|
|
22
|
+
|
|
23
|
+
# Raised when a zone change operation fails.
|
|
24
|
+
class ZoneChangeError < Error; end
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
# Loads the Beamer SQLite extension for the current process.
|
|
28
|
+
#
|
|
29
|
+
# This registers the Beamer VFS globally with SQLite, enabling all subsequent
|
|
30
|
+
# database connections to use it. The VFS provides SQLite replication functionality.
|
|
31
|
+
#
|
|
32
|
+
# @return [SQLite3::Database] A temporary in-memory database used to load the extension
|
|
33
|
+
# @raise [UnsupportedPlatform] if the current platform doesn't have a precompiled extension
|
|
34
|
+
#
|
|
35
|
+
# @example
|
|
36
|
+
# Beamer.load
|
|
37
|
+
#
|
|
38
|
+
# @note This is called automatically when using `adapter: beamer` in database.yml.
|
|
39
|
+
# You typically don't need to call this manually if you are using Rails.
|
|
40
|
+
def load
|
|
41
|
+
if extension_path
|
|
42
|
+
SQLite3::Database.new(":memory:").tap do |db|
|
|
43
|
+
db.enable_load_extension(true)
|
|
44
|
+
db.load_extension(extension_path)
|
|
45
|
+
end
|
|
46
|
+
else
|
|
47
|
+
raise UnsupportedPlatform, "Unsupported platform: #{platform}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns the file system path to the Beamer SQLite extension for the current platform.
|
|
54
|
+
#
|
|
55
|
+
# @return [String, nil] Path to beamer extension, or nil if not found
|
|
56
|
+
#
|
|
57
|
+
# @example
|
|
58
|
+
# Beamer.extension_path
|
|
59
|
+
# # => "/path/to/gem/exe/x86_64-linux-gnu/beamer.so"
|
|
60
|
+
def extension_path
|
|
61
|
+
exe_path = "#{exe_dir}/beamer.so"
|
|
62
|
+
|
|
63
|
+
if File.exist?(exe_path)
|
|
64
|
+
exe_path
|
|
65
|
+
else
|
|
66
|
+
nil
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Returns the directory containing platform-specific executables and extensions.
|
|
71
|
+
#
|
|
72
|
+
# @return [String] Absolute path to the exe directory for the current platform
|
|
73
|
+
#
|
|
74
|
+
# @example
|
|
75
|
+
# Beamer.exe_dir
|
|
76
|
+
# # => "/path/to/gem/exe/x86_64-linux-gnu"
|
|
77
|
+
def exe_dir
|
|
78
|
+
File.expand_path("../../exe/#{platform}", __FILE__)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns the normalized platform string for the current system.
|
|
82
|
+
#
|
|
83
|
+
# This method normalizes platform identifiers to match RubyGems conventions,
|
|
84
|
+
# adding the `-gnu` suffix to glibc-based Linux platforms.
|
|
85
|
+
#
|
|
86
|
+
# @return [String] Platform identifier (e.g., "x86_64-linux-gnu", "arm64-darwin")
|
|
87
|
+
#
|
|
88
|
+
# @example
|
|
89
|
+
# Beamer.platform
|
|
90
|
+
# # => "x86_64-linux-gnu" (on Ubuntu/Debian)
|
|
91
|
+
# # => "x86_64-linux-musl" (on Alpine Linux)
|
|
92
|
+
# # => "arm64-darwin" (on Apple Silicon Mac)
|
|
93
|
+
def platform
|
|
94
|
+
Beamer::NATIVE_PLATFORMS.keys.find { |p| Gem::Platform.match_gem?(Gem::Platform.new(p), GEM_NAME) } ||
|
|
95
|
+
raise(UnsupportedPlatform, "Can not find a matching platform for: #{Gem::Platform.local}")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: beamer-rails
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0.beta4
|
|
5
|
+
platform: arm64-linux-musl
|
|
6
|
+
authors:
|
|
7
|
+
- Kevin McConnell
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: sqlite3
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rails
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '7.1'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '7.1'
|
|
40
|
+
email:
|
|
41
|
+
- kevin@37signals.com
|
|
42
|
+
executables:
|
|
43
|
+
- beamer
|
|
44
|
+
extensions: []
|
|
45
|
+
extra_rdoc_files: []
|
|
46
|
+
files:
|
|
47
|
+
- LICENSE.txt
|
|
48
|
+
- exe/arm64-linux-musl/beamer
|
|
49
|
+
- exe/arm64-linux-musl/beamer.so
|
|
50
|
+
- exe/beamer
|
|
51
|
+
- lib/beamer-rails.rb
|
|
52
|
+
- lib/beamer.rb
|
|
53
|
+
- lib/beamer/connection_adapter.rb
|
|
54
|
+
- lib/beamer/railtie.rb
|
|
55
|
+
- lib/beamer/tenanted_database_adapter.rb
|
|
56
|
+
- lib/beamer/version.rb
|
|
57
|
+
homepage: https://github.com/basecamp/beamer
|
|
58
|
+
licenses:
|
|
59
|
+
- MIT
|
|
60
|
+
metadata:
|
|
61
|
+
homepage_uri: https://github.com/basecamp/beamer
|
|
62
|
+
source_code_uri: https://github.com/basecamp/beamer
|
|
63
|
+
rubygems_mfa_required: 'true'
|
|
64
|
+
github_repo: ssh://github.com/basecamp/beamer
|
|
65
|
+
rdoc_options: []
|
|
66
|
+
require_paths:
|
|
67
|
+
- lib
|
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
69
|
+
requirements:
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: 3.2.0
|
|
73
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
|
+
requirements:
|
|
75
|
+
- - ">="
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
78
|
+
requirements: []
|
|
79
|
+
rubygems_version: 3.6.9
|
|
80
|
+
specification_version: 4
|
|
81
|
+
summary: Beamer SQLite replication for Rails
|
|
82
|
+
test_files: []
|