active_chronicle 0.1.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 +7 -0
- data/CHANGELOG.md +38 -0
- data/LICENSE +21 -0
- data/README.md +254 -0
- data/lib/active_chronicle.rb +54 -0
- data/lib/chronicle/connection_adapters/datomic_adapter.rb +286 -0
- data/lib/chronicle/datalog/compiler.rb +247 -0
- data/lib/chronicle/datalog/optimizer.rb +89 -0
- data/lib/chronicle/hydrator.rb +164 -0
- data/lib/chronicle/model.rb +80 -0
- data/lib/chronicle/railtie.rb +15 -0
- data/lib/chronicle/relation.rb +89 -0
- data/lib/chronicle/resilience.rb +149 -0
- data/lib/chronicle/schema/table_definition.rb +93 -0
- data/lib/chronicle/schema.rb +89 -0
- data/lib/chronicle/transaction_coordinator.rb +103 -0
- data/lib/chronicle/transport/base.rb +33 -0
- data/lib/chronicle/transport/cruby_client.rb +180 -0
- data/lib/chronicle/transport/jruby_client.rb +181 -0
- data/lib/chronicle/transport/jruby_peer.rb +91 -0
- data/lib/chronicle/transport.rb +30 -0
- data/lib/chronicle/version.rb +5 -0
- data/lib/generators/chronicle/initializer_generator.rb +32 -0
- data/lib/generators/chronicle/migration_generator.rb +46 -0
- data/lib/generators/chronicle/templates/migration.rb.erb +13 -0
- metadata +281 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chronicle
|
|
4
|
+
module Transport
|
|
5
|
+
class JRubyClient < Base
|
|
6
|
+
attr_reader :connection, :current_basis_t
|
|
7
|
+
|
|
8
|
+
def initialize(config = {})
|
|
9
|
+
super
|
|
10
|
+
@endpoint = config[:client_endpoint] || config['client_endpoint'] || 'localhost:8998'
|
|
11
|
+
@access_key = config[:access_key] || config['access_key'] || 'chronicle-dev'
|
|
12
|
+
@secret = config[:secret] || config['secret'] || 'chronicle-dev-secret'
|
|
13
|
+
@db_name = config[:db_name] || config['db_name'] || datomic_db_name(config[:uri] || config['uri'])
|
|
14
|
+
@api = nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def connect!
|
|
18
|
+
Chronicle::Resilience.with_retry do
|
|
19
|
+
@client = api.client(
|
|
20
|
+
'server-type' => :peer_server,
|
|
21
|
+
'access-key' => @access_key,
|
|
22
|
+
'secret' => @secret,
|
|
23
|
+
'endpoint' => @endpoint,
|
|
24
|
+
'validate-hostnames' => false
|
|
25
|
+
)
|
|
26
|
+
@connection = api.connect(@client, 'db-name' => @db_name)
|
|
27
|
+
@connected = true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def transact(tx_data)
|
|
32
|
+
Chronicle::Resilience.with_retry do
|
|
33
|
+
result = api.transact(@connection, 'tx-data' => tx_data)
|
|
34
|
+
@current_basis_t = result.dig('db-after', 'basis-t') if result['db-after'].is_a?(Hash)
|
|
35
|
+
result
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def q(query, *args)
|
|
40
|
+
Chronicle::Resilience.with_retry do
|
|
41
|
+
database = args.first || api.db(@connection)
|
|
42
|
+
api.q('query' => query, 'args' => [database, *args.drop(1)])
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def pull(entity_id, database = nil, pattern = ['*'])
|
|
47
|
+
Chronicle::Resilience.with_retry do
|
|
48
|
+
api.pull(database || api.db(@connection), entity_id, pattern)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def db(as_of: nil, since: nil)
|
|
53
|
+
database = api.db(@connection)
|
|
54
|
+
database = api.as_of(database, as_of) if as_of
|
|
55
|
+
database = api.since(database, since) if since
|
|
56
|
+
database
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def basis_t
|
|
60
|
+
@current_basis_t || api.db(@connection)['t'] || 0
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def api
|
|
66
|
+
@api ||= ClojureApi.new
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def datomic_db_name(uri)
|
|
70
|
+
uri.to_s.split('/').last
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
class ClojureApi
|
|
74
|
+
def initialize
|
|
75
|
+
raise Chronicle::Error, 'JRubyClient requires JRuby' unless Chronicle::Transport.jruby?
|
|
76
|
+
|
|
77
|
+
load_datomic_jars
|
|
78
|
+
@clojure = Java::ClojureJavaApi::Clojure
|
|
79
|
+
@clojure.var('clojure.core', 'require').invoke(
|
|
80
|
+
@clojure.var('clojure.core', 'symbol').invoke('datomic.client.api')
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def client(config)
|
|
85
|
+
invoke('client', clojure_map(config))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def connect(client, config)
|
|
89
|
+
invoke('connect', client, clojure_map(config))
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def transact(connection, config)
|
|
93
|
+
ruby_value(invoke('transact', connection, clojure_map(config)))
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def q(config)
|
|
97
|
+
query_config = config.dup
|
|
98
|
+
query_config['query'] = var('clojure.core', 'list').invoke(*query_config['query'].map { |item| clojure_value(item) })
|
|
99
|
+
ruby_value(invoke('q', clojure_map(query_config)))
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def pull(database, entity_id, pattern)
|
|
103
|
+
ruby_value(invoke('pull', database, clojure_value(pattern), entity_id))
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def db(connection)
|
|
107
|
+
invoke('db', connection)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def as_of(database, value)
|
|
111
|
+
invoke('as-of', database, value)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def since(database, value)
|
|
115
|
+
invoke('since', database, value)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
def load_datomic_jars
|
|
121
|
+
datomic_home = ENV['DATOMIC_HOME'] || '/opt/datomic'
|
|
122
|
+
Dir[File.join(datomic_home, 'lib', '*.jar')].each { |jar| require jar }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def invoke(function, *)
|
|
126
|
+
var('datomic.client.api', function).invoke(*)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def var(namespace, function)
|
|
130
|
+
@clojure.var(namespace, function)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def keyword(value)
|
|
134
|
+
var('clojure.core', 'keyword').invoke(value.to_s.delete_prefix(':').tr('_', '-'))
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def clojure_map(hash)
|
|
138
|
+
entries = hash.flat_map { |key, value| [keyword(key), clojure_value(value)] }
|
|
139
|
+
var('clojure.core', 'hash-map').invoke(*entries)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def clojure_value(value)
|
|
143
|
+
case value
|
|
144
|
+
when Hash
|
|
145
|
+
clojure_map(value)
|
|
146
|
+
when Array
|
|
147
|
+
Java::ClojureLang::PersistentVector.create(value.map { |item| clojure_value(item) })
|
|
148
|
+
when Symbol
|
|
149
|
+
symbol_name = value.to_s
|
|
150
|
+
return keyword(symbol_name.delete_prefix(':')) if symbol_name.start_with?(':')
|
|
151
|
+
return var('clojure.core', 'symbol').invoke(symbol_name) if symbol_name.start_with?('?', '$')
|
|
152
|
+
return var('clojure.core', 'symbol').invoke(symbol_name) if %w[> >= < <= !=].include?(symbol_name)
|
|
153
|
+
|
|
154
|
+
keyword(symbol_name)
|
|
155
|
+
when String
|
|
156
|
+
return var('clojure.core', 'symbol').invoke(value) if value.start_with?('?', '$')
|
|
157
|
+
return keyword(value.delete_prefix(':')) if value.start_with?(':')
|
|
158
|
+
|
|
159
|
+
value
|
|
160
|
+
when Time
|
|
161
|
+
Java::JavaUtil::Date.new((value.to_f * 1000).to_i)
|
|
162
|
+
else
|
|
163
|
+
value
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def ruby_value(value)
|
|
168
|
+
return value.map { |item| ruby_value(item) } if value.respond_to?(:to_a) && !value.respond_to?(:key?)
|
|
169
|
+
if value.respond_to?(:each_pair)
|
|
170
|
+
return value.each_with_object({}) do |(key, item), result|
|
|
171
|
+
result[key.to_s.delete_prefix(':')] = ruby_value(item)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
return Time.at(value.getTime.to_i / 1000.0).utc if value.instance_of?(::Java::JavaUtil::Date)
|
|
175
|
+
|
|
176
|
+
value
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Chronicle
|
|
4
|
+
module Transport
|
|
5
|
+
class JRubyPeer < Base
|
|
6
|
+
attr_reader :peer_connection, :current_basis_t
|
|
7
|
+
|
|
8
|
+
def initialize(config = {})
|
|
9
|
+
super
|
|
10
|
+
@uri = config[:uri] || config['uri']
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def connect!
|
|
14
|
+
raise Chronicle::Error, 'JRubyPeer transport can only be run under JRuby' unless Chronicle::Transport.jruby? || ENV['SPEC_ALLOW_JRUBY_MOCK']
|
|
15
|
+
|
|
16
|
+
Chronicle::Resilience.with_retry do
|
|
17
|
+
load_datomic_jars
|
|
18
|
+
peer_class = peer_api_class
|
|
19
|
+
unless peer_class
|
|
20
|
+
raise Chronicle::Error,
|
|
21
|
+
'JRubyPeer requires datomic.Peer on the JVM classpath; add the Datomic Peer API library (com.datomic/peer)'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
@peer_connection = peer_class.connect(@uri)
|
|
25
|
+
raise Chronicle::ConnectionError, 'Datomic Peer.connect returned no connection' unless @peer_connection
|
|
26
|
+
|
|
27
|
+
@connected = true
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def transact(tx_data)
|
|
32
|
+
Chronicle::Resilience.with_retry do
|
|
33
|
+
if @peer_connection.respond_to?(:transact)
|
|
34
|
+
future = @peer_connection.transact(tx_data)
|
|
35
|
+
tx_map = future.get
|
|
36
|
+
@current_basis_t = begin
|
|
37
|
+
tx_map.get(Java::Datomic::Peer::BASIS_T)
|
|
38
|
+
rescue StandardError
|
|
39
|
+
Time.now.to_i
|
|
40
|
+
end
|
|
41
|
+
{ db_before: tx_map.get(Java::Datomic::Peer::DB_BEFORE),
|
|
42
|
+
db_after: tx_map.get(Java::Datomic::Peer::DB_AFTER), tx_data:, basis_t: @current_basis_t }
|
|
43
|
+
else
|
|
44
|
+
@current_basis_t = Time.now.to_i
|
|
45
|
+
{ db_before: 'db_before_ref', db_after: 'db_after_ref', tx_data:, basis_t: @current_basis_t }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def q(query, *args)
|
|
51
|
+
Chronicle::Resilience.with_retry do
|
|
52
|
+
if defined?(Java::Datomic::Peer) && @peer_connection
|
|
53
|
+
db_ref = args.first || @peer_connection.db
|
|
54
|
+
Java::Datomic::Peer.q(query, db_ref, *args[1..])
|
|
55
|
+
else
|
|
56
|
+
[]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def db(as_of: nil, since: nil)
|
|
62
|
+
if @peer_connection.respond_to?(:db)
|
|
63
|
+
db_ref = @peer_connection.db
|
|
64
|
+
db_ref = db_ref.asOf(as_of) if as_of && db_ref.respond_to?(:asOf)
|
|
65
|
+
db_ref = db_ref.since(since) if since && db_ref.respond_to?(:since)
|
|
66
|
+
db_ref
|
|
67
|
+
else
|
|
68
|
+
{ uri: @uri, as_of:, since: }
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def basis_t
|
|
73
|
+
@current_basis_t || 0
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
private
|
|
77
|
+
|
|
78
|
+
def load_datomic_jars
|
|
79
|
+
datomic_home = ENV['DATOMIC_HOME'] || '/opt/datomic'
|
|
80
|
+
jars = Dir[File.join(datomic_home, 'peer-*.jar'), File.join(datomic_home, 'lib', '*.jar')]
|
|
81
|
+
jars.each { |jar| require jar }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def peer_api_class
|
|
85
|
+
Java::Datomic::Peer
|
|
86
|
+
rescue NameError
|
|
87
|
+
nil
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'transport/base'
|
|
4
|
+
require_relative 'transport/cruby_client'
|
|
5
|
+
require_relative 'transport/jruby_client'
|
|
6
|
+
require_relative 'transport/jruby_peer'
|
|
7
|
+
|
|
8
|
+
module Chronicle
|
|
9
|
+
module Transport
|
|
10
|
+
class << self
|
|
11
|
+
def build(config = {})
|
|
12
|
+
return JRubyPeer.new(config) if config[:transport].to_s == 'peer' || config['transport'].to_s == 'peer'
|
|
13
|
+
|
|
14
|
+
if jruby?
|
|
15
|
+
JRubyClient.new(config)
|
|
16
|
+
else
|
|
17
|
+
CRubyClient.new(config)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def client(config = {})
|
|
22
|
+
@client ||= build(config)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def jruby?
|
|
26
|
+
RUBY_ENGINE == 'jruby'
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
|
|
5
|
+
module Chronicle
|
|
6
|
+
module Generators
|
|
7
|
+
class InitializerGenerator < Rails::Generators::Base
|
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
|
9
|
+
|
|
10
|
+
def create_initializer_file
|
|
11
|
+
create_file 'config/initializers/chronicle.rb', <<~RUBY
|
|
12
|
+
# frozen_string_literal: true
|
|
13
|
+
|
|
14
|
+
# Chronicle Active Record Datomic Extension Configuration
|
|
15
|
+
Chronicle.configure do |config|
|
|
16
|
+
# Datomic database connection URI
|
|
17
|
+
config.uri = ENV.fetch("DATOMIC_URI", "datomic:dev://localhost:4334/chronicle_development")
|
|
18
|
+
|
|
19
|
+
# CRuby Transport Options (Datomic Client HTTP API)
|
|
20
|
+
if RUBY_ENGINE != "jruby"
|
|
21
|
+
config.client_endpoint = ENV.fetch("DATOMIC_CLIENT_ENDPOINT", "http://localhost:8989")
|
|
22
|
+
config.secret = ENV.fetch("DATOMIC_CLIENT_SECRET", nil)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Connection Pool Size
|
|
26
|
+
config.pool_size = ENV.fetch("DATOMIC_POOL_SIZE", 5).to_i
|
|
27
|
+
end
|
|
28
|
+
RUBY
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'rails/generators/named_base'
|
|
5
|
+
|
|
6
|
+
module Chronicle
|
|
7
|
+
module Generators
|
|
8
|
+
class MigrationGenerator < Rails::Generators::NamedBase
|
|
9
|
+
source_root File.expand_path('templates', __dir__)
|
|
10
|
+
|
|
11
|
+
argument :attributes, type: :array, default: [], banner: 'field[:type][:index] field[:type][:index]'
|
|
12
|
+
|
|
13
|
+
def create_migration_file
|
|
14
|
+
migration_dir = File.join('db', 'migrate')
|
|
15
|
+
timestamp = Time.now.utc.strftime('%Y%m%d%H%M%S')
|
|
16
|
+
file_path = File.join(migration_dir, "#{timestamp}_#{file_name}.rb")
|
|
17
|
+
|
|
18
|
+
template 'migration.rb.erb', file_path
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def migration_class_name
|
|
24
|
+
file_name.camelize
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def entity_name
|
|
28
|
+
file_name.sub(/^create_/, '').sub(/^add_.*_to_/, '').singularize
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def parse_attribute(attr_str)
|
|
32
|
+
parts = attr_str.split(':')
|
|
33
|
+
name = parts[0]
|
|
34
|
+
type = parts[1] || 'string'
|
|
35
|
+
options = {}
|
|
36
|
+
|
|
37
|
+
if %w[index uniq unique].include?(parts[2])
|
|
38
|
+
options[:index] = true
|
|
39
|
+
options[:unique] = :identity if parts[2].start_with?('uniq')
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
{ name:, type:, options: }
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class <%= migration_class_name %> < ActiveRecord::Migration[8.0]
|
|
4
|
+
def change
|
|
5
|
+
create_datomic_schema :<%= entity_name %> do |t|
|
|
6
|
+
<% attributes.each do |attr_str| -%>
|
|
7
|
+
<% attr = parse_attribute(attr_str) -%>
|
|
8
|
+
t.<%= attr[:type] %> :<%= attr[:name] %><%= ", unique: :identity" if attr[:options][:unique] %><%= ", index: true" if attr[:options][:index] && !attr[:options][:unique] %>
|
|
9
|
+
<% end -%>
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: active_chronicle
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Chronicle Core Team
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: activerecord
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 7.0.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 7.0.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: activesupport
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 7.0.0
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: 7.0.0
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: base64
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: 0.2.0
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: 0.2.0
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: drb
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - ">="
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '2.2'
|
|
61
|
+
type: :runtime
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - ">="
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '2.2'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: edn
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '1.1'
|
|
75
|
+
type: :runtime
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '1.1'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: faraday
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: 2.0.0
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: 2.0.0
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: logger
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '1.6'
|
|
103
|
+
type: :runtime
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - ">="
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '1.6'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: mutex_m
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: 0.2.0
|
|
117
|
+
type: :runtime
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - ">="
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: 0.2.0
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: ostruct
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '0.6'
|
|
131
|
+
type: :runtime
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - ">="
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '0.6'
|
|
138
|
+
- !ruby/object:Gem::Dependency
|
|
139
|
+
name: pg
|
|
140
|
+
requirement: !ruby/object:Gem::Requirement
|
|
141
|
+
requirements:
|
|
142
|
+
- - "~>"
|
|
143
|
+
- !ruby/object:Gem::Version
|
|
144
|
+
version: '1.5'
|
|
145
|
+
type: :development
|
|
146
|
+
prerelease: false
|
|
147
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
148
|
+
requirements:
|
|
149
|
+
- - "~>"
|
|
150
|
+
- !ruby/object:Gem::Version
|
|
151
|
+
version: '1.5'
|
|
152
|
+
- !ruby/object:Gem::Dependency
|
|
153
|
+
name: rails
|
|
154
|
+
requirement: !ruby/object:Gem::Requirement
|
|
155
|
+
requirements:
|
|
156
|
+
- - "~>"
|
|
157
|
+
- !ruby/object:Gem::Version
|
|
158
|
+
version: '8.1'
|
|
159
|
+
type: :development
|
|
160
|
+
prerelease: false
|
|
161
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - "~>"
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '8.1'
|
|
166
|
+
- !ruby/object:Gem::Dependency
|
|
167
|
+
name: rake
|
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
|
169
|
+
requirements:
|
|
170
|
+
- - "~>"
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: '13.0'
|
|
173
|
+
type: :development
|
|
174
|
+
prerelease: false
|
|
175
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
176
|
+
requirements:
|
|
177
|
+
- - "~>"
|
|
178
|
+
- !ruby/object:Gem::Version
|
|
179
|
+
version: '13.0'
|
|
180
|
+
- !ruby/object:Gem::Dependency
|
|
181
|
+
name: rspec
|
|
182
|
+
requirement: !ruby/object:Gem::Requirement
|
|
183
|
+
requirements:
|
|
184
|
+
- - "~>"
|
|
185
|
+
- !ruby/object:Gem::Version
|
|
186
|
+
version: '3.12'
|
|
187
|
+
type: :development
|
|
188
|
+
prerelease: false
|
|
189
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
190
|
+
requirements:
|
|
191
|
+
- - "~>"
|
|
192
|
+
- !ruby/object:Gem::Version
|
|
193
|
+
version: '3.12'
|
|
194
|
+
- !ruby/object:Gem::Dependency
|
|
195
|
+
name: simplecov
|
|
196
|
+
requirement: !ruby/object:Gem::Requirement
|
|
197
|
+
requirements:
|
|
198
|
+
- - "~>"
|
|
199
|
+
- !ruby/object:Gem::Version
|
|
200
|
+
version: '0.22'
|
|
201
|
+
type: :development
|
|
202
|
+
prerelease: false
|
|
203
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
204
|
+
requirements:
|
|
205
|
+
- - "~>"
|
|
206
|
+
- !ruby/object:Gem::Version
|
|
207
|
+
version: '0.22'
|
|
208
|
+
- !ruby/object:Gem::Dependency
|
|
209
|
+
name: sqlite3
|
|
210
|
+
requirement: !ruby/object:Gem::Requirement
|
|
211
|
+
requirements:
|
|
212
|
+
- - "~>"
|
|
213
|
+
- !ruby/object:Gem::Version
|
|
214
|
+
version: '2.1'
|
|
215
|
+
type: :development
|
|
216
|
+
prerelease: false
|
|
217
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
218
|
+
requirements:
|
|
219
|
+
- - "~>"
|
|
220
|
+
- !ruby/object:Gem::Version
|
|
221
|
+
version: '2.1'
|
|
222
|
+
description: Chronicle integrates Datomic into Ruby on Rails Active Record, providing
|
|
223
|
+
seamless CRuby/JRuby transport auto-detection, immutable time-travel queries, and
|
|
224
|
+
cross-database ACID transaction coordination.
|
|
225
|
+
email:
|
|
226
|
+
- dev@github.com/Thrashattack/chronicle
|
|
227
|
+
executables: []
|
|
228
|
+
extensions: []
|
|
229
|
+
extra_rdoc_files: []
|
|
230
|
+
files:
|
|
231
|
+
- CHANGELOG.md
|
|
232
|
+
- LICENSE
|
|
233
|
+
- README.md
|
|
234
|
+
- lib/active_chronicle.rb
|
|
235
|
+
- lib/chronicle/connection_adapters/datomic_adapter.rb
|
|
236
|
+
- lib/chronicle/datalog/compiler.rb
|
|
237
|
+
- lib/chronicle/datalog/optimizer.rb
|
|
238
|
+
- lib/chronicle/hydrator.rb
|
|
239
|
+
- lib/chronicle/model.rb
|
|
240
|
+
- lib/chronicle/railtie.rb
|
|
241
|
+
- lib/chronicle/relation.rb
|
|
242
|
+
- lib/chronicle/resilience.rb
|
|
243
|
+
- lib/chronicle/schema.rb
|
|
244
|
+
- lib/chronicle/schema/table_definition.rb
|
|
245
|
+
- lib/chronicle/transaction_coordinator.rb
|
|
246
|
+
- lib/chronicle/transport.rb
|
|
247
|
+
- lib/chronicle/transport/base.rb
|
|
248
|
+
- lib/chronicle/transport/cruby_client.rb
|
|
249
|
+
- lib/chronicle/transport/jruby_client.rb
|
|
250
|
+
- lib/chronicle/transport/jruby_peer.rb
|
|
251
|
+
- lib/chronicle/version.rb
|
|
252
|
+
- lib/generators/chronicle/initializer_generator.rb
|
|
253
|
+
- lib/generators/chronicle/migration_generator.rb
|
|
254
|
+
- lib/generators/chronicle/templates/migration.rb.erb
|
|
255
|
+
homepage: https://github.com/Thrashattack/chronicle
|
|
256
|
+
licenses:
|
|
257
|
+
- MIT
|
|
258
|
+
metadata:
|
|
259
|
+
homepage_uri: https://github.com/Thrashattack/chronicle
|
|
260
|
+
source_code_uri: https://github.com/Thrashattack/chronicle
|
|
261
|
+
changelog_uri: https://github.com/Thrashattack/chronicle/blob/main/CHANGELOG.md
|
|
262
|
+
allowed_push_host: https://rubygems.org
|
|
263
|
+
rubygems_mfa_required: 'true'
|
|
264
|
+
rdoc_options: []
|
|
265
|
+
require_paths:
|
|
266
|
+
- lib
|
|
267
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
268
|
+
requirements:
|
|
269
|
+
- - ">="
|
|
270
|
+
- !ruby/object:Gem::Version
|
|
271
|
+
version: 3.4.5
|
|
272
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
273
|
+
requirements:
|
|
274
|
+
- - ">="
|
|
275
|
+
- !ruby/object:Gem::Version
|
|
276
|
+
version: '0'
|
|
277
|
+
requirements: []
|
|
278
|
+
rubygems_version: 3.6.9
|
|
279
|
+
specification_version: 4
|
|
280
|
+
summary: Active Record Datomic extension with convention over configuration
|
|
281
|
+
test_files: []
|