ree_lib 1.0.49 → 1.0.50
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -3
- data/lib/ree_lib/Packages.schema.json +4 -0
- data/lib/ree_lib/packages/ree_actions/spec/ree_actions/dsl_spec.rb +17 -10
- data/lib/ree_lib/packages/ree_dao/Package.schema.json +10 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/aggregate_dsl.rb +26 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/association.rb +311 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/associations.rb +148 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/beans/dao_cache.rb +40 -19
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/contract/dao_dataset_contract.rb +15 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/contract/entity_contract.rb +15 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/dataset_extensions.rb +4 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/dsl.rb +1 -1
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/build_pg_connection.rb +1 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/build_sqlite_connection.rb +1 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/drop_cache.rb +1 -1
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/init_cache.rb +1 -1
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/load_agg.rb +63 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/thread_parents.rb +40 -0
- data/lib/ree_lib/packages/ree_dao/package/ree_dao.rb +9 -0
- data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/build_pg_connection.schema.json +1 -1
- data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/build_sqlite_connection.schema.json +1 -1
- data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/load_agg.schema.json +43 -0
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/load_agg_benchmark_spec.rb +414 -0
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/load_agg_spec.rb +605 -0
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/ree_dao_load_agg_test.rb +524 -0
- data/lib/ree_lib/packages/ree_logger/package/ree_logger/multi_logger.rb +19 -10
- data/lib/ree_lib/packages/ree_logger/spec/ree_logger/multi_logger_spec.rb +10 -0
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory_proxy.rb +6 -3
- data/lib/ree_lib/packages/ree_std/.gitignore +0 -0
- data/lib/ree_lib/packages/ree_std/.rspec +2 -0
- data/lib/ree_lib/packages/ree_std/Package.schema.json +24 -0
- data/lib/ree_lib/packages/ree_std/bin/console +5 -0
- data/lib/ree_lib/packages/ree_std/package/ree_std/functions/retry_on_fail.rb +46 -0
- data/lib/ree_lib/packages/ree_std/package/ree_std/retry.rb +67 -0
- data/lib/ree_lib/packages/ree_std/package/ree_std.rb +6 -0
- data/lib/ree_lib/packages/ree_std/schemas/ree_std/functions/retry_on_fail.schema.json +38 -0
- data/lib/ree_lib/packages/ree_std/spec/package_schema_spec.rb +14 -0
- data/lib/ree_lib/packages/ree_std/spec/ree_std/functions/retry_on_fail_spec.rb +97 -0
- data/lib/ree_lib/packages/ree_std/spec/spec_helper.rb +3 -0
- data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_request_body_schema.rb +5 -0
- data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_serializer_schema.rb +5 -0
- data/lib/ree_lib/packages/ree_swagger/spec/functions/build_endpoint_schema_spec.rb +4 -2
- data/lib/ree_lib/packages/ree_swagger/spec/functions/build_request_body_spec.rb +4 -2
- data/lib/ree_lib/version.rb +1 -1
- metadata +38 -2
@@ -0,0 +1,15 @@
|
|
1
|
+
class ReeDao::DaoDatasetContract
|
2
|
+
extend Ree::Contracts::Truncatable
|
3
|
+
|
4
|
+
def self.valid?(obj)
|
5
|
+
obj.class.ancestors.include?(ReeDao::DatasetExtensions::InstanceMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.to_s
|
9
|
+
"PackageName::DaoName::Dao: \"SELECT * FROM `table`\""
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.message(value, name, lvl = 1)
|
13
|
+
"expected #{to_s}, got => #{truncate(value.inspect)}"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class ReeDao::EntityContract
|
2
|
+
extend Ree::Contracts::Truncatable
|
3
|
+
|
4
|
+
def self.valid?(obj)
|
5
|
+
obj.class.ancestors.include?(ReeDto::EntityDSL)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.to_s
|
9
|
+
"PackageName::Entity"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.message(value, name, lvl = 1)
|
13
|
+
"expected #{to_s}, got => #{truncate(value.inspect)}"
|
14
|
+
end
|
15
|
+
end
|
@@ -111,6 +111,10 @@ module ReeDao
|
|
111
111
|
nil
|
112
112
|
end
|
113
113
|
|
114
|
+
def ids(ids_list)
|
115
|
+
where(id: ids_list)
|
116
|
+
end
|
117
|
+
|
114
118
|
def update(hash_or_entity)
|
115
119
|
return __original_update(hash_or_entity) if !opts[:schema_mapper]
|
116
120
|
return __original_update(hash_or_entity) if hash_or_entity.is_a?(Hash)
|
@@ -16,7 +16,7 @@ module ReeDao::DSL
|
|
16
16
|
module InstanceMethods
|
17
17
|
def build
|
18
18
|
dataset_class = db.dataset_class
|
19
|
-
klass = Class.new(dataset_class)
|
19
|
+
klass = self.class.const_set(:Dao, Class.new(dataset_class))
|
20
20
|
filters = self.class.instance_variable_get(:@filters) || []
|
21
21
|
|
22
22
|
filters.each do |filter|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ReeDao::LoadAgg
|
4
|
+
include Ree::FnDSL
|
5
|
+
|
6
|
+
fn :load_agg do
|
7
|
+
link "ree_dao/associations", -> { Associations }
|
8
|
+
link "ree_dao/contract/dao_dataset_contract", -> { DaoDatasetContract }
|
9
|
+
link "ree_dao/contract/entity_contract", -> { EntityContract }
|
10
|
+
end
|
11
|
+
|
12
|
+
contract(
|
13
|
+
Or[Sequel::Dataset, ArrayOf[Integer], ArrayOf[EntityContract], Integer],
|
14
|
+
Nilor[DaoDatasetContract],
|
15
|
+
Ksplat[
|
16
|
+
only?: ArrayOf[Symbol],
|
17
|
+
except?: ArrayOf[Symbol],
|
18
|
+
RestKeys => Any
|
19
|
+
],
|
20
|
+
Optblock => ArrayOf[Any]
|
21
|
+
)
|
22
|
+
def call(ids_or_scope, dao = nil, **opts, &block)
|
23
|
+
scope = if ids_or_scope.is_a?(Array) && ids_or_scope.any? { _1.is_a?(Integer) }
|
24
|
+
raise ArgumentError.new("Dao should be provided") if dao.nil?
|
25
|
+
return [] if ids_or_scope.empty?
|
26
|
+
|
27
|
+
dao.where(id: ids_or_scope)
|
28
|
+
elsif ids_or_scope.is_a?(Integer)
|
29
|
+
raise ArgumentError.new("Dao should be provided") if dao.nil?
|
30
|
+
|
31
|
+
dao.where(id: ids_or_scope)
|
32
|
+
else
|
33
|
+
ids_or_scope
|
34
|
+
end
|
35
|
+
|
36
|
+
list = scope.is_a?(Sequel::Dataset) ? scope.all : scope
|
37
|
+
|
38
|
+
load_associations(list, **opts, &block) if block_given?
|
39
|
+
|
40
|
+
if ids_or_scope.is_a?(Array)
|
41
|
+
list.sort_by { ids_or_scope.index(_1.id) }
|
42
|
+
else
|
43
|
+
list
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def load_associations(list, **opts, &block)
|
50
|
+
local_vars = block.binding.eval(<<-CODE, __FILE__, __LINE__ + 1)
|
51
|
+
vars = self.instance_variables
|
52
|
+
vars.reduce({}) { |hsh, var| hsh[var] = self.instance_variable_get(var); hsh }
|
53
|
+
CODE
|
54
|
+
|
55
|
+
agg_caller = block.binding.eval("self")
|
56
|
+
|
57
|
+
if ReeDao.load_sync_associations_enabled?
|
58
|
+
Associations.new(agg_caller, list, local_vars, **opts).instance_exec(list, &block)
|
59
|
+
else
|
60
|
+
Associations.new(agg_caller, list, local_vars, **opts).instance_exec(list, &block).map(&:join)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module ThreadParent
|
4
|
+
class Parents
|
5
|
+
|
6
|
+
def initialize(child)
|
7
|
+
@child = child
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](key)
|
11
|
+
if @child.key?(key)
|
12
|
+
@child[key]
|
13
|
+
elsif @child.parent
|
14
|
+
@child.parent.parents[key]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Thread
|
21
|
+
|
22
|
+
alias_method :_initialize, :initialize
|
23
|
+
|
24
|
+
def initialize(*args, &block)
|
25
|
+
@_parent = Thread.current
|
26
|
+
_initialize(*args, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def parent
|
30
|
+
@_parent
|
31
|
+
end
|
32
|
+
|
33
|
+
def parents
|
34
|
+
ThreadParent::Parents.new(self)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.parents
|
38
|
+
ThreadParent::Parents.new(Thread.current)
|
39
|
+
end
|
40
|
+
end
|
@@ -12,9 +12,14 @@ module ReeDao
|
|
12
12
|
depends_on :ree_mapper
|
13
13
|
depends_on :ree_string
|
14
14
|
depends_on :ree_object
|
15
|
+
depends_on :ree_hash
|
15
16
|
end
|
16
17
|
|
17
18
|
require_relative "./ree_dao/dsl"
|
19
|
+
require_relative "./ree_dao/thread_parents"
|
20
|
+
require_relative "./ree_dao/aggregate_dsl"
|
21
|
+
require_relative "./ree_dao/associations"
|
22
|
+
require_relative "./ree_dao/association"
|
18
23
|
|
19
24
|
def self.init_cache(thread)
|
20
25
|
ReeDao::Cache.init_cache(thread)
|
@@ -23,4 +28,8 @@ module ReeDao
|
|
23
28
|
def self.drop_cache(thread)
|
24
29
|
ReeDao::Cache.delete_cache(thread)
|
25
30
|
end
|
31
|
+
|
32
|
+
def self.load_sync_associations_enabled?
|
33
|
+
ENV.has_key?("REE_DAO_SYNC_ASSOCIATIONS") && ENV["REE_DAO_SYNC_ASSOCIATIONS"] == "true"
|
34
|
+
end
|
26
35
|
end
|
@@ -17,7 +17,7 @@
|
|
17
17
|
{
|
18
18
|
"arg": "conn_opts",
|
19
19
|
"arg_type": "req",
|
20
|
-
"type": "{:conn_str? => String, :adapter => String, :database? => String, :encoding? => String, :user? => String, :password? => String, :host? => String, :port? => Or[String, Integer], :convert_infinite_timestamps? => Or[string, nil, float], :connect_timeout? => Integer, :driver_options? => Hash, :notice_receiver? => Proc, :sslmode? => Or[disable, allow, prefer, require, verify-ca, verify-full...], :sslrootcert? => String, :search_path? => String, :use_iso_date_format? => Bool, :max_connections? => Integer}"
|
20
|
+
"type": "{:conn_str? => String, :adapter => String, :database? => String, :encoding? => String, :user? => String, :password? => String, :host? => String, :port? => Or[String, Integer], :convert_infinite_timestamps? => Or[string, nil, float], :connect_timeout? => Integer, :driver_options? => Hash, :notice_receiver? => Proc, :sslmode? => Or[disable, allow, prefer, require, verify-ca, verify-full...], :sslrootcert? => String, :search_path? => String, :use_iso_date_format? => Bool, :max_connections? => Integer, :pool_timeout? => Integer}"
|
21
21
|
},
|
22
22
|
{
|
23
23
|
"arg": "opts",
|
data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/build_sqlite_connection.schema.json
CHANGED
@@ -17,7 +17,7 @@
|
|
17
17
|
{
|
18
18
|
"arg": "conn_opts",
|
19
19
|
"arg_type": "req",
|
20
|
-
"type": "{:database => String, :readonly? => Bool, :timeout? => Integer, :max_connections? => Integer}"
|
20
|
+
"type": "{:database => String, :readonly? => Bool, :timeout? => Integer, :max_connections? => Integer, :pool_timeout? => Integer}"
|
21
21
|
},
|
22
22
|
{
|
23
23
|
"arg": "opts",
|
@@ -0,0 +1,43 @@
|
|
1
|
+
{
|
2
|
+
"schema_type": "object",
|
3
|
+
"schema_version": "1.1",
|
4
|
+
"name": "load_agg",
|
5
|
+
"path": "packages/ree_dao/package/ree_dao/functions/load_agg.rb",
|
6
|
+
"mount_as": "fn",
|
7
|
+
"class": "ReeDao::LoadAgg",
|
8
|
+
"factory": null,
|
9
|
+
"methods": [
|
10
|
+
{
|
11
|
+
"doc": "",
|
12
|
+
"throws": [
|
13
|
+
|
14
|
+
],
|
15
|
+
"return": "ArrayOf[Any]",
|
16
|
+
"args": [
|
17
|
+
{
|
18
|
+
"arg": "ids_or_scope",
|
19
|
+
"arg_type": "req",
|
20
|
+
"type": "Or[Sequel::Dataset, ArrayOf[Integer], ArrayOf[PackageName::Entity], Integer]"
|
21
|
+
},
|
22
|
+
{
|
23
|
+
"arg": "dao",
|
24
|
+
"arg_type": "opt",
|
25
|
+
"type": "Nilor[PackageName::DaoName::Dao: \"SELECT * FROM `table`\"]"
|
26
|
+
},
|
27
|
+
{
|
28
|
+
"arg": "opts",
|
29
|
+
"arg_type": "keyrest",
|
30
|
+
"type": "Ksplat[:only? => ArrayOf[Symbol], :except? => ArrayOf[Symbol], \"RestKeys\" => Any]"
|
31
|
+
},
|
32
|
+
{
|
33
|
+
"arg": "block",
|
34
|
+
"arg_type": "block",
|
35
|
+
"type": "Block"
|
36
|
+
}
|
37
|
+
]
|
38
|
+
}
|
39
|
+
],
|
40
|
+
"links": [
|
41
|
+
|
42
|
+
]
|
43
|
+
}
|
@@ -0,0 +1,414 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'faker'
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
RSpec.describe :load_agg do
|
6
|
+
link :build_pg_connection, from: :ree_dao
|
7
|
+
link :load_agg, from: :ree_dao
|
8
|
+
|
9
|
+
NUM_OF_USERS = 100
|
10
|
+
ASSOC_COUNT = 10
|
11
|
+
|
12
|
+
after do
|
13
|
+
Ree.disable_irb_mode
|
14
|
+
end
|
15
|
+
|
16
|
+
before :all do
|
17
|
+
connection = build_pg_connection(ReeDaoLoadAggTest::Db::DB_CONFIG)
|
18
|
+
|
19
|
+
connection.drop_table(:organizations, cascade: true) if connection.table_exists?(:organizations)
|
20
|
+
connection.drop_table(:users, cascade: true) if connection.table_exists?(:users)
|
21
|
+
connection.drop_table(:user_passports, cascade: true) if connection.table_exists?(:user_passports)
|
22
|
+
connection.drop_table(:books, cascade: true) if connection.table_exists?(:books)
|
23
|
+
connection.drop_table(:movies, cascade: true) if connection.table_exists?(:movies)
|
24
|
+
connection.drop_table(:videogames, cascade: true) if connection.table_exists?(:videogames)
|
25
|
+
connection.drop_table(:hobbies, cascade: true) if connection.table_exists?(:hobbies)
|
26
|
+
connection.drop_table(:vinyls, cascade: true) if connection.table_exists?(:vinyls)
|
27
|
+
connection.drop_table(:pets, cascade: true) if connection.table_exists?(:pets)
|
28
|
+
connection.drop_table(:skills, cascade: true) if connection.table_exists?(:skills)
|
29
|
+
connection.drop_table(:dreams, cascade: true) if connection.table_exists?(:dreams)
|
30
|
+
|
31
|
+
connection.create_table :organizations do
|
32
|
+
primary_key :id
|
33
|
+
|
34
|
+
column :name, 'varchar(256)'
|
35
|
+
end
|
36
|
+
|
37
|
+
connection.create_table :users do
|
38
|
+
primary_key :id
|
39
|
+
|
40
|
+
column :name, 'varchar(256)'
|
41
|
+
column :age, :integer
|
42
|
+
foreign_key :organization_id, :organizations, null: false, on_delete: :cascade
|
43
|
+
end
|
44
|
+
|
45
|
+
connection.create_table :user_passports do
|
46
|
+
primary_key :id
|
47
|
+
|
48
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
49
|
+
column :info, 'varchar(256)'
|
50
|
+
end
|
51
|
+
|
52
|
+
connection.create_table :books do
|
53
|
+
primary_key :id
|
54
|
+
|
55
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
56
|
+
column :title, 'varchar(256)'
|
57
|
+
end
|
58
|
+
|
59
|
+
connection.create_table :movies do
|
60
|
+
primary_key :id
|
61
|
+
|
62
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
63
|
+
column :title, 'varchar(256)'
|
64
|
+
end
|
65
|
+
|
66
|
+
connection.create_table :videogames do
|
67
|
+
primary_key :id
|
68
|
+
|
69
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
70
|
+
column :title, 'varchar(256)'
|
71
|
+
end
|
72
|
+
|
73
|
+
connection.create_table :hobbies do
|
74
|
+
primary_key :id
|
75
|
+
|
76
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
77
|
+
column :title, 'varchar(256)'
|
78
|
+
end
|
79
|
+
|
80
|
+
connection.create_table :vinyls do
|
81
|
+
primary_key :id
|
82
|
+
|
83
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
84
|
+
column :title, 'varchar(256)'
|
85
|
+
end
|
86
|
+
|
87
|
+
connection.create_table :pets do
|
88
|
+
primary_key :id
|
89
|
+
|
90
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
91
|
+
column :name, 'varchar(256)'
|
92
|
+
end
|
93
|
+
|
94
|
+
connection.create_table :skills do
|
95
|
+
primary_key :id
|
96
|
+
|
97
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
98
|
+
column :title, 'varchar(256)'
|
99
|
+
end
|
100
|
+
|
101
|
+
connection.create_table :dreams do
|
102
|
+
primary_key :id
|
103
|
+
|
104
|
+
foreign_key :user_id, :users, null: false, on_delete: :cascade
|
105
|
+
column :description, 'varchar(256)'
|
106
|
+
end
|
107
|
+
|
108
|
+
connection.disconnect
|
109
|
+
end
|
110
|
+
|
111
|
+
require_relative 'ree_dao_load_agg_test'
|
112
|
+
|
113
|
+
class ReeDaoLoadAggTest::UsersAggBenchmark
|
114
|
+
include ReeDao::AggregateDSL
|
115
|
+
|
116
|
+
aggregate :users_agg_benchmark do
|
117
|
+
link :users, from: :ree_dao_load_agg_test
|
118
|
+
link :organizations, from: :ree_dao_load_agg_test
|
119
|
+
link :user_passports, from: :ree_dao_load_agg_test
|
120
|
+
link :books, from: :ree_dao_load_agg_test
|
121
|
+
link :movies, from: :ree_dao_load_agg_test
|
122
|
+
link :videogames, from: :ree_dao_load_agg_test
|
123
|
+
link :hobbies, from: :ree_dao_load_agg_test
|
124
|
+
link :vinyls, from: :ree_dao_load_agg_test
|
125
|
+
link :pets, from: :ree_dao_load_agg_test
|
126
|
+
link :skills, from: :ree_dao_load_agg_test
|
127
|
+
link :dreams, from: :ree_dao_load_agg_test
|
128
|
+
link :load_agg, from: :ree_dao
|
129
|
+
end
|
130
|
+
|
131
|
+
def call(ids_or_scope)
|
132
|
+
load_agg(ids_or_scope, users) do
|
133
|
+
belongs_to :organization
|
134
|
+
|
135
|
+
has_many :books
|
136
|
+
has_many :movies
|
137
|
+
has_many :videogames
|
138
|
+
has_many :hobbies
|
139
|
+
has_many :vinyls
|
140
|
+
has_many :pets
|
141
|
+
has_many :skills
|
142
|
+
has_many :dreams
|
143
|
+
|
144
|
+
has_one :passport, foreign_key: :user_id, scope: user_passports
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
class ReeDaoLoadAggTest::UsersSyncFetcher
|
150
|
+
include Ree::FnDSL
|
151
|
+
|
152
|
+
fn :users_sync_fetcher do
|
153
|
+
link :users, from: :ree_dao_load_agg_test
|
154
|
+
link :organizations, from: :ree_dao_load_agg_test
|
155
|
+
link :user_passports, from: :ree_dao_load_agg_test
|
156
|
+
link :books, from: :ree_dao_load_agg_test
|
157
|
+
link :movies, from: :ree_dao_load_agg_test
|
158
|
+
link :videogames, from: :ree_dao_load_agg_test
|
159
|
+
link :hobbies, from: :ree_dao_load_agg_test
|
160
|
+
link :vinyls, from: :ree_dao_load_agg_test
|
161
|
+
link :pets, from: :ree_dao_load_agg_test
|
162
|
+
link :skills, from: :ree_dao_load_agg_test
|
163
|
+
link :dreams, from: :ree_dao_load_agg_test
|
164
|
+
link :one_to_many, from: :ree_dao
|
165
|
+
link :one_to_one, from: :ree_dao
|
166
|
+
end
|
167
|
+
|
168
|
+
contract(
|
169
|
+
Or[Sequel::Dataset, ArrayOf[Integer]],
|
170
|
+
Kwargs[
|
171
|
+
include: ArrayOf[Symbol]
|
172
|
+
] => ArrayOf[ReeDaoLoadAggTest::User]
|
173
|
+
)
|
174
|
+
def call(ids_or_scope, include: [])
|
175
|
+
scope = if ids_or_scope.is_a?(Array)
|
176
|
+
return [] if ids_or_scope.empty?
|
177
|
+
users.where(id: ids_or_scope)
|
178
|
+
else
|
179
|
+
ids_or_scope
|
180
|
+
end
|
181
|
+
|
182
|
+
list = scope.all
|
183
|
+
return [] if list.empty?
|
184
|
+
|
185
|
+
if include.include?(:organization)
|
186
|
+
one_to_one(list, organizations.order(:id))
|
187
|
+
end
|
188
|
+
|
189
|
+
if include.include?(:books)
|
190
|
+
one_to_many(list, books.order(:id))
|
191
|
+
end
|
192
|
+
|
193
|
+
if include.include?(:movies)
|
194
|
+
one_to_many(list, movies.order(:id))
|
195
|
+
end
|
196
|
+
|
197
|
+
if include.include?(:videogames)
|
198
|
+
one_to_many(list, videogames.order(:id))
|
199
|
+
end
|
200
|
+
|
201
|
+
if include.include?(:hobbies)
|
202
|
+
one_to_many(list, hobbies.order(:id), assoc_setter: :set_hobbies)
|
203
|
+
end
|
204
|
+
|
205
|
+
if include.include?(:skills)
|
206
|
+
one_to_many(list, skills.order(:id))
|
207
|
+
end
|
208
|
+
|
209
|
+
if include.include?(:vinyls)
|
210
|
+
one_to_many(list, vinyls.order(:id))
|
211
|
+
end
|
212
|
+
|
213
|
+
if include.include?(:pets)
|
214
|
+
one_to_many(list, pets.order(:id))
|
215
|
+
end
|
216
|
+
|
217
|
+
if include.include?(:dreams)
|
218
|
+
one_to_many(list, dreams.order(:id))
|
219
|
+
end
|
220
|
+
|
221
|
+
if include.include?(:passport)
|
222
|
+
one_to_one(list, user_passports.order(:id), reverse: true, assoc_setter: :set_passport)
|
223
|
+
end
|
224
|
+
|
225
|
+
if ids_or_scope.is_a?(Array)
|
226
|
+
list.sort_by { ids_or_scope.index(_1.id) }
|
227
|
+
else
|
228
|
+
list
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
let(:users_agg) { ReeDaoLoadAggTest::UsersAggBenchmark.new }
|
234
|
+
let(:users_sync_fetcher) { ReeDaoLoadAggTest::UsersSyncFetcher.new }
|
235
|
+
|
236
|
+
let(:organizations) { ReeDaoLoadAggTest::Organizations.new }
|
237
|
+
let(:users) { ReeDaoLoadAggTest::Users.new }
|
238
|
+
let(:user_passports) { ReeDaoLoadAggTest::UserPassports.new }
|
239
|
+
let(:books) { ReeDaoLoadAggTest::Books.new }
|
240
|
+
let(:movies) { ReeDaoLoadAggTest::Movies.new }
|
241
|
+
let(:videogames) { ReeDaoLoadAggTest::Videogames.new }
|
242
|
+
let(:hobbies) { ReeDaoLoadAggTest::Hobbies.new }
|
243
|
+
let(:vinyls) { ReeDaoLoadAggTest::Vinyls.new }
|
244
|
+
let(:pets) { ReeDaoLoadAggTest::Pets.new }
|
245
|
+
let(:skills) { ReeDaoLoadAggTest::Skills.new }
|
246
|
+
let(:dreams) { ReeDaoLoadAggTest::Dreams.new }
|
247
|
+
|
248
|
+
before(:each) do
|
249
|
+
organization = ReeDaoLoadAggTest::Organization.new(name: "Test Org")
|
250
|
+
organizations.put(organization)
|
251
|
+
|
252
|
+
_users = []
|
253
|
+
st_time = Time.now
|
254
|
+
puts "Starting to seed #{NUM_OF_USERS} users..."
|
255
|
+
NUM_OF_USERS.times do
|
256
|
+
u = ReeDaoLoadAggTest::User.new(
|
257
|
+
name: Faker::Name.name,
|
258
|
+
age: rand(18..50),
|
259
|
+
organization_id: organization.id
|
260
|
+
)
|
261
|
+
|
262
|
+
_users << u
|
263
|
+
users.put(u)
|
264
|
+
end
|
265
|
+
|
266
|
+
_users.each do |user|
|
267
|
+
ASSOC_COUNT.times do
|
268
|
+
books.put(
|
269
|
+
ReeDaoLoadAggTest::Book.new(
|
270
|
+
title: Faker::Book.title,
|
271
|
+
user_id: user.id
|
272
|
+
)
|
273
|
+
)
|
274
|
+
end
|
275
|
+
|
276
|
+
ASSOC_COUNT.times do
|
277
|
+
movies.put(
|
278
|
+
ReeDaoLoadAggTest::Movie.new(
|
279
|
+
user_id: user.id,
|
280
|
+
title: Faker::Movie.title
|
281
|
+
)
|
282
|
+
)
|
283
|
+
end
|
284
|
+
|
285
|
+
ASSOC_COUNT.times do
|
286
|
+
videogames.put(
|
287
|
+
ReeDaoLoadAggTest::Videogame.new(
|
288
|
+
user_id: user.id,
|
289
|
+
title: Faker::Game.title
|
290
|
+
)
|
291
|
+
)
|
292
|
+
end
|
293
|
+
|
294
|
+
ASSOC_COUNT.times do
|
295
|
+
hobbies.put(
|
296
|
+
ReeDaoLoadAggTest::Hobby.new(
|
297
|
+
user_id: user.id,
|
298
|
+
title: Faker::Hobby.activity
|
299
|
+
)
|
300
|
+
)
|
301
|
+
end
|
302
|
+
|
303
|
+
ASSOC_COUNT.times do
|
304
|
+
vinyls.put(
|
305
|
+
ReeDaoLoadAggTest::Vinyl.new(
|
306
|
+
user_id: user.id,
|
307
|
+
title: Faker::Music.band
|
308
|
+
)
|
309
|
+
)
|
310
|
+
end
|
311
|
+
|
312
|
+
ASSOC_COUNT.times do
|
313
|
+
pets.put(
|
314
|
+
ReeDaoLoadAggTest::Pet.new(
|
315
|
+
user_id: user.id,
|
316
|
+
name: Faker::Creature::Animal.name
|
317
|
+
)
|
318
|
+
)
|
319
|
+
end
|
320
|
+
|
321
|
+
ASSOC_COUNT.times do
|
322
|
+
skills.put(
|
323
|
+
ReeDaoLoadAggTest::Skill.new(
|
324
|
+
user_id: user.id,
|
325
|
+
title: Faker::Job.key_skill
|
326
|
+
)
|
327
|
+
)
|
328
|
+
end
|
329
|
+
|
330
|
+
ASSOC_COUNT.times do
|
331
|
+
dreams.put(
|
332
|
+
ReeDaoLoadAggTest::Dream.new(
|
333
|
+
user_id: user.id,
|
334
|
+
description: Faker::ChuckNorris.fact
|
335
|
+
)
|
336
|
+
)
|
337
|
+
end
|
338
|
+
|
339
|
+
ASSOC_COUNT.times do
|
340
|
+
user_passports.put(
|
341
|
+
ReeDaoLoadAggTest::UserPassport.new(
|
342
|
+
user_id: user.id,
|
343
|
+
info: "Passport info #{user.id}"
|
344
|
+
)
|
345
|
+
)
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
puts "Seeding is complete! #{Time.now - st_time}"
|
350
|
+
end
|
351
|
+
|
352
|
+
it {
|
353
|
+
res1 = nil
|
354
|
+
res2 = nil
|
355
|
+
res3 = nil
|
356
|
+
|
357
|
+
benchmark_res = Benchmark.bm do |x|
|
358
|
+
x.report("async_load_agg") do
|
359
|
+
res1 = users_agg.call(users.all.map(&:id))
|
360
|
+
end
|
361
|
+
|
362
|
+
x.report("sync_load_agg ") do
|
363
|
+
ENV['REE_DAO_SYNC_ASSOCIATIONS'] = "true"
|
364
|
+
res2 = users_agg.call(users.all.map(&:id))
|
365
|
+
ENV.delete('REE_DAO_SYNC_ASSOCIATIONS')
|
366
|
+
end
|
367
|
+
|
368
|
+
x.report("sync_fetcher ") do
|
369
|
+
res3 = users_sync_fetcher.call(
|
370
|
+
users.all.map(&:id),
|
371
|
+
include: [
|
372
|
+
:organization,
|
373
|
+
:books,
|
374
|
+
:movies,
|
375
|
+
:videogames,
|
376
|
+
:hobbies,
|
377
|
+
:vinyls,
|
378
|
+
:pets,
|
379
|
+
:skills,
|
380
|
+
:dreams,
|
381
|
+
:passport
|
382
|
+
]
|
383
|
+
)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
expect(res1).to eq(res3)
|
388
|
+
expect(res1[0].organization).to eq(res3[0].organization)
|
389
|
+
expect(res1[0].passport).to eq(res3[0].passport)
|
390
|
+
expect(res1[0].books).to eq(res3[0].books)
|
391
|
+
expect(res1[0].movies).to eq(res3[0].movies)
|
392
|
+
expect(res1[0].books).to eq(res3[0].books)
|
393
|
+
expect(res1[0].videogames).to eq(res3[0].videogames)
|
394
|
+
expect(res1[0].hobbies).to eq(res3[0].hobbies)
|
395
|
+
expect(res1[0].vinyls).to eq(res3[0].vinyls)
|
396
|
+
expect(res1[0].pets).to eq(res3[0].pets)
|
397
|
+
expect(res1[0].skills).to eq(res3[0].skills)
|
398
|
+
expect(res1[0].dreams).to eq(res3[0].dreams)
|
399
|
+
|
400
|
+
expect(res2).to eq(res3)
|
401
|
+
expect(res2[0].organization).to eq(res3[0].organization)
|
402
|
+
expect(res2[0].books).to eq(res3[0].books)
|
403
|
+
expect(res2[0].movies).to eq(res3[0].movies)
|
404
|
+
expect(res2[0].videogames).to eq(res3[0].videogames)
|
405
|
+
expect(res2[0].hobbies).to eq(res3[0].hobbies)
|
406
|
+
expect(res2[0].vinyls).to eq(res3[0].vinyls)
|
407
|
+
expect(res2[0].pets).to eq(res3[0].pets)
|
408
|
+
expect(res2[0].skills).to eq(res3[0].skills)
|
409
|
+
expect(res2[0].dreams).to eq(res3[0].dreams)
|
410
|
+
|
411
|
+
# expect(benchmark_res[0].real).to be < benchmark_res[1].real
|
412
|
+
# expect(benchmark_res[0].real).to be < benchmark_res[2].real
|
413
|
+
}
|
414
|
+
end
|