activegraph 11.0.0.beta.1-java

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.
Files changed (144) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +2016 -0
  3. data/CONTRIBUTORS +12 -0
  4. data/Gemfile +24 -0
  5. data/README.md +111 -0
  6. data/activegraph.gemspec +52 -0
  7. data/bin/rake +17 -0
  8. data/config/locales/en.yml +5 -0
  9. data/config/neo4j/add_classnames.yml +1 -0
  10. data/config/neo4j/config.yml +35 -0
  11. data/lib/active_graph.rb +123 -0
  12. data/lib/active_graph/ansi.rb +14 -0
  13. data/lib/active_graph/attribute_set.rb +32 -0
  14. data/lib/active_graph/base.rb +77 -0
  15. data/lib/active_graph/class_arguments.rb +39 -0
  16. data/lib/active_graph/config.rb +135 -0
  17. data/lib/active_graph/core.rb +14 -0
  18. data/lib/active_graph/core/connection_failed_error.rb +6 -0
  19. data/lib/active_graph/core/cypher_error.rb +37 -0
  20. data/lib/active_graph/core/entity.rb +11 -0
  21. data/lib/active_graph/core/instrumentable.rb +37 -0
  22. data/lib/active_graph/core/label.rb +135 -0
  23. data/lib/active_graph/core/logging.rb +44 -0
  24. data/lib/active_graph/core/node.rb +15 -0
  25. data/lib/active_graph/core/querable.rb +41 -0
  26. data/lib/active_graph/core/query.rb +485 -0
  27. data/lib/active_graph/core/query_builder.rb +18 -0
  28. data/lib/active_graph/core/query_clauses.rb +727 -0
  29. data/lib/active_graph/core/query_ext.rb +24 -0
  30. data/lib/active_graph/core/query_find_in_batches.rb +46 -0
  31. data/lib/active_graph/core/record.rb +51 -0
  32. data/lib/active_graph/core/result.rb +31 -0
  33. data/lib/active_graph/core/schema.rb +65 -0
  34. data/lib/active_graph/core/schema_errors.rb +12 -0
  35. data/lib/active_graph/core/wrappable.rb +30 -0
  36. data/lib/active_graph/errors.rb +59 -0
  37. data/lib/active_graph/lazy_attribute_hash.rb +38 -0
  38. data/lib/active_graph/migration.rb +148 -0
  39. data/lib/active_graph/migrations.rb +27 -0
  40. data/lib/active_graph/migrations/base.rb +77 -0
  41. data/lib/active_graph/migrations/check_pending.rb +20 -0
  42. data/lib/active_graph/migrations/helpers.rb +105 -0
  43. data/lib/active_graph/migrations/helpers/id_property.rb +72 -0
  44. data/lib/active_graph/migrations/helpers/relationships.rb +66 -0
  45. data/lib/active_graph/migrations/helpers/schema.rb +63 -0
  46. data/lib/active_graph/migrations/migration_file.rb +24 -0
  47. data/lib/active_graph/migrations/runner.rb +195 -0
  48. data/lib/active_graph/migrations/schema.rb +64 -0
  49. data/lib/active_graph/migrations/schema_migration.rb +14 -0
  50. data/lib/active_graph/model_schema.rb +139 -0
  51. data/lib/active_graph/node.rb +110 -0
  52. data/lib/active_graph/node/callbacks.rb +8 -0
  53. data/lib/active_graph/node/dependent.rb +11 -0
  54. data/lib/active_graph/node/dependent/association_methods.rb +49 -0
  55. data/lib/active_graph/node/dependent/query_proxy_methods.rb +52 -0
  56. data/lib/active_graph/node/dependent_callbacks.rb +31 -0
  57. data/lib/active_graph/node/enum.rb +26 -0
  58. data/lib/active_graph/node/has_n.rb +602 -0
  59. data/lib/active_graph/node/has_n/association.rb +278 -0
  60. data/lib/active_graph/node/has_n/association/rel_factory.rb +61 -0
  61. data/lib/active_graph/node/has_n/association/rel_wrapper.rb +23 -0
  62. data/lib/active_graph/node/has_n/association_cypher_methods.rb +108 -0
  63. data/lib/active_graph/node/id_property.rb +224 -0
  64. data/lib/active_graph/node/id_property/accessor.rb +62 -0
  65. data/lib/active_graph/node/initialize.rb +21 -0
  66. data/lib/active_graph/node/labels.rb +207 -0
  67. data/lib/active_graph/node/labels/index.rb +37 -0
  68. data/lib/active_graph/node/labels/reloading.rb +21 -0
  69. data/lib/active_graph/node/node_list_formatter.rb +13 -0
  70. data/lib/active_graph/node/node_wrapper.rb +54 -0
  71. data/lib/active_graph/node/orm_adapter.rb +82 -0
  72. data/lib/active_graph/node/persistence.rb +186 -0
  73. data/lib/active_graph/node/property.rb +60 -0
  74. data/lib/active_graph/node/query.rb +76 -0
  75. data/lib/active_graph/node/query/query_proxy.rb +367 -0
  76. data/lib/active_graph/node/query/query_proxy_eager_loading.rb +177 -0
  77. data/lib/active_graph/node/query/query_proxy_eager_loading/association_tree.rb +75 -0
  78. data/lib/active_graph/node/query/query_proxy_enumerable.rb +110 -0
  79. data/lib/active_graph/node/query/query_proxy_find_in_batches.rb +19 -0
  80. data/lib/active_graph/node/query/query_proxy_link.rb +139 -0
  81. data/lib/active_graph/node/query/query_proxy_methods.rb +303 -0
  82. data/lib/active_graph/node/query/query_proxy_methods_of_mass_updating.rb +99 -0
  83. data/lib/active_graph/node/query_methods.rb +68 -0
  84. data/lib/active_graph/node/reflection.rb +86 -0
  85. data/lib/active_graph/node/rels.rb +11 -0
  86. data/lib/active_graph/node/scope.rb +166 -0
  87. data/lib/active_graph/node/unpersisted.rb +48 -0
  88. data/lib/active_graph/node/validations.rb +59 -0
  89. data/lib/active_graph/paginated.rb +27 -0
  90. data/lib/active_graph/railtie.rb +108 -0
  91. data/lib/active_graph/relationship.rb +68 -0
  92. data/lib/active_graph/relationship/callbacks.rb +21 -0
  93. data/lib/active_graph/relationship/initialize.rb +28 -0
  94. data/lib/active_graph/relationship/persistence.rb +133 -0
  95. data/lib/active_graph/relationship/persistence/query_factory.rb +95 -0
  96. data/lib/active_graph/relationship/property.rb +92 -0
  97. data/lib/active_graph/relationship/query.rb +99 -0
  98. data/lib/active_graph/relationship/rel_wrapper.rb +31 -0
  99. data/lib/active_graph/relationship/related_node.rb +87 -0
  100. data/lib/active_graph/relationship/types.rb +80 -0
  101. data/lib/active_graph/relationship/validations.rb +8 -0
  102. data/lib/active_graph/schema/operation.rb +102 -0
  103. data/lib/active_graph/shared.rb +48 -0
  104. data/lib/active_graph/shared/attributes.rb +217 -0
  105. data/lib/active_graph/shared/callbacks.rb +66 -0
  106. data/lib/active_graph/shared/cypher.rb +37 -0
  107. data/lib/active_graph/shared/declared_properties.rb +204 -0
  108. data/lib/active_graph/shared/declared_property.rb +109 -0
  109. data/lib/active_graph/shared/declared_property/index.rb +37 -0
  110. data/lib/active_graph/shared/enum.rb +167 -0
  111. data/lib/active_graph/shared/filtered_hash.rb +79 -0
  112. data/lib/active_graph/shared/identity.rb +34 -0
  113. data/lib/active_graph/shared/initialize.rb +65 -0
  114. data/lib/active_graph/shared/marshal.rb +23 -0
  115. data/lib/active_graph/shared/mass_assignment.rb +63 -0
  116. data/lib/active_graph/shared/permitted_attributes.rb +28 -0
  117. data/lib/active_graph/shared/persistence.rb +272 -0
  118. data/lib/active_graph/shared/property.rb +249 -0
  119. data/lib/active_graph/shared/query_factory.rb +122 -0
  120. data/lib/active_graph/shared/rel_type_converters.rb +43 -0
  121. data/lib/active_graph/shared/serialized_properties.rb +30 -0
  122. data/lib/active_graph/shared/type_converters.rb +439 -0
  123. data/lib/active_graph/shared/typecasted_attributes.rb +99 -0
  124. data/lib/active_graph/shared/typecaster.rb +53 -0
  125. data/lib/active_graph/shared/validations.rb +44 -0
  126. data/lib/active_graph/tasks/migration.rake +204 -0
  127. data/lib/active_graph/timestamps.rb +11 -0
  128. data/lib/active_graph/timestamps/created.rb +9 -0
  129. data/lib/active_graph/timestamps/updated.rb +9 -0
  130. data/lib/active_graph/transaction.rb +22 -0
  131. data/lib/active_graph/transactions.rb +57 -0
  132. data/lib/active_graph/type_converters.rb +7 -0
  133. data/lib/active_graph/undeclared_properties.rb +53 -0
  134. data/lib/active_graph/version.rb +3 -0
  135. data/lib/active_graph/wrapper.rb +4 -0
  136. data/lib/rails/generators/active_graph/migration/migration_generator.rb +16 -0
  137. data/lib/rails/generators/active_graph/migration/templates/migration.erb +9 -0
  138. data/lib/rails/generators/active_graph/model/model_generator.rb +89 -0
  139. data/lib/rails/generators/active_graph/model/templates/migration.erb +11 -0
  140. data/lib/rails/generators/active_graph/model/templates/model.erb +15 -0
  141. data/lib/rails/generators/active_graph/upgrade_v8/templates/migration.erb +17 -0
  142. data/lib/rails/generators/active_graph/upgrade_v8/upgrade_v8_generator.rb +34 -0
  143. data/lib/rails/generators/active_graph_generator.rb +121 -0
  144. metadata +423 -0
@@ -0,0 +1,24 @@
1
+ module ActiveGraph
2
+ module Core
3
+ class Query
4
+ # Creates a ActiveGraph::Node::Query::QueryProxy object that builds off of a Core::Query object.
5
+ #
6
+ # @param [Class] model An Node model to be used as the start of a new QueryuProxy chain
7
+ # @param [Symbol] var The variable to be used to refer to the object from within the new QueryProxy
8
+ # @param [Boolean] optional Indicate whether the new QueryProxy will use MATCH or OPTIONAL MATCH.
9
+ # @return [ActiveGraph::Node::Query::QueryProxy] A QueryProxy object.
10
+ def proxy_as(model, var, optional = false)
11
+ # TODO: Discuss whether it's necessary to call `break` on the query or if this should be left to the user.
12
+ ActiveGraph::Node::Query::QueryProxy.new(model, nil, node: var, optional: optional, starting_query: self, chain_level: @proxy_chain_level)
13
+ end
14
+
15
+ # Calls proxy_as with `optional` set true. This doesn't offer anything different from calling `proxy_as` directly but it may be more readable.
16
+ def proxy_as_optional(model, var)
17
+ proxy_as(model, var, true)
18
+ end
19
+
20
+ # For instances where you turn a QueryProxy into a Query and then back to a QueryProxy with `#proxy_as`
21
+ attr_accessor :proxy_chain_level
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,46 @@
1
+ module ActiveGraph
2
+ module Core
3
+ module QueryFindInBatches
4
+ def find_in_batches(node_var, prop_var, options = {})
5
+ validate_find_in_batches_options!(options)
6
+
7
+ batch_size = options.delete(:batch_size) || 1000
8
+
9
+ query = reorder(node_var => prop_var).limit(batch_size)
10
+
11
+ records = query.to_a
12
+
13
+ while records.any?
14
+ records_size = records.size
15
+ primary_key_offset = primary_key_offset(records.last, node_var, prop_var)
16
+
17
+ yield records
18
+
19
+ break if records_size < batch_size
20
+
21
+ primary_key_var = ActiveGraph::Core::QueryClauses::Clause.from_key_and_single_value(node_var, prop_var)
22
+ records = query.where("#{primary_key_var} > $primary_key_offset")
23
+ .params(primary_key_offset: primary_key_offset).to_a
24
+ end
25
+ end
26
+
27
+ def find_each(*args, &block)
28
+ find_in_batches(*args) { |batch| batch.each(&block) }
29
+ end
30
+
31
+ private
32
+
33
+ def validate_find_in_batches_options!(options)
34
+ invalid_keys = options.keys.map(&:to_sym) - [:batch_size]
35
+ fail ArgumentError, "Invalid keys: #{invalid_keys.join(', ')}" if not invalid_keys.empty?
36
+ end
37
+
38
+ def primary_key_offset(last_record, node_var, prop_var)
39
+ node = last_record[node_var]
40
+ return node.send(prop_var) if node&.respond_to?(prop_var)
41
+ return node.properties[prop_var.to_sym] if node&.respond_to?(:properties)
42
+ last_record["#{node_var}.#{prop_var}"] # In case we're explicitly returning it
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_graph/core/result'
4
+ require 'active_support/core_ext/module/attribute_accessors'
5
+
6
+ module ActiveGraph
7
+ module Core
8
+ module Record
9
+ attr_writer :wrap
10
+
11
+ def values
12
+ wrap(super)
13
+ end
14
+
15
+ def first
16
+ wrap(super)
17
+ end
18
+
19
+ def [](key)
20
+ wrap(super)
21
+ end
22
+
23
+ def to_h
24
+ wrap(super)
25
+ end
26
+
27
+ private
28
+
29
+ def wrap(value)
30
+ return value unless wrap?
31
+
32
+ case value
33
+ when Neo4j::Driver::Types::Entity
34
+ value.wrap
35
+ when Neo4j::Driver::Types::Path
36
+ value
37
+ when Hash
38
+ value.transform_values(&method(:wrap))
39
+ when Enumerable
40
+ value.map!(&method(:wrap))
41
+ else
42
+ value
43
+ end
44
+ end
45
+
46
+ def wrap?
47
+ @wrap
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,31 @@
1
+ module ActiveGraph
2
+ module Core
3
+ module Result
4
+ attr_writer :wrap
5
+
6
+ def keys
7
+ @keys ||= super
8
+ end
9
+
10
+ def wrap?
11
+ @wrap
12
+ end
13
+
14
+ def each(&block)
15
+ store if wrap? # TODO: why? This is preventing streaming
16
+ @records&.each(&block) || super
17
+ end
18
+
19
+ def store
20
+ return if @records
21
+ keys
22
+ @records = []
23
+ # TODO: implement 'each' without block parameter
24
+ method(:each).super_method.call do |record|
25
+ record.wrap = wrap?
26
+ @records << record
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,65 @@
1
+ module ActiveGraph
2
+ module Core
3
+ module Schema
4
+ def version
5
+ read_transaction do
6
+ # BTW: community / enterprise could be retrieved via `result.first.edition`
7
+ query('CALL dbms.components()', {}, skip_instrumentation: true).first[:versions][0]
8
+ end
9
+ end
10
+
11
+ def indexes
12
+ read_transaction do
13
+ result = query('CALL db.indexes()', {}, skip_instrumentation: true)
14
+
15
+ result.map do |row|
16
+ { type: row[:type].to_sym, label: label(result, row), properties: properties(row),
17
+ state: row[:state].to_sym }
18
+ end
19
+ end
20
+ end
21
+
22
+ def constraints
23
+ read_transaction do
24
+ result = query('CALL db.indexes()', {}, skip_instrumentation: true)
25
+
26
+ result.select(&method(v4?(result) ? :v4_filter : :v3_filter)).map do |row|
27
+ { type: :uniqueness, label: label(result, row), properties: properties(row) }
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def v4_filter(row)
35
+ row[:uniqueness] == 'UNIQUE'
36
+ end
37
+
38
+ def v3_filter(row)
39
+ row[:type] == 'node_unique_property'
40
+ end
41
+
42
+ def label(result, row)
43
+ if v34?(result)
44
+ row[:label]
45
+ else
46
+ (v4?(result) ? row[:labelsOrTypes] : row[:tokenNames]).first
47
+ end.to_sym
48
+ end
49
+
50
+ def v4?(result)
51
+ return @v4 unless @v4.nil?
52
+ @v4 = result.keys.include?(:labelsOrTypes)
53
+ end
54
+
55
+ def v34?(result)
56
+ return @v34 unless @v34.nil?
57
+ @v34 = result.keys.include?(:label)
58
+ end
59
+
60
+ def properties(row)
61
+ row[:properties].map(&:to_sym)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,12 @@
1
+ module ActiveGraph
2
+ module Core
3
+ module SchemaErrors
4
+ class ConstraintValidationFailedError < CypherError;
5
+ end
6
+ class ConstraintAlreadyExistsError < CypherError;
7
+ end
8
+ class IndexAlreadyExistsError < CypherError;
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,30 @@
1
+ module ActiveGraph
2
+ module Core
3
+ module Wrappable
4
+ extend ActiveSupport::Concern
5
+
6
+ def wrap
7
+ self.class.wrap(self)
8
+ end
9
+
10
+ class_methods do
11
+ def wrapper_callback(proc)
12
+ fail 'Callback already specified!' if @wrapper_callback
13
+ @wrapper_callback = proc
14
+ end
15
+
16
+ def clear_wrapper_callback
17
+ @wrapper_callback = nil
18
+ end
19
+
20
+ def wrap(node)
21
+ if @wrapper_callback
22
+ @wrapper_callback.call(node)
23
+ else
24
+ node
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,59 @@
1
+ module ActiveGraph
2
+ # Neo4j.rb Errors
3
+ # Generic Neo4j.rb exception class.
4
+ class Error < StandardError
5
+ end
6
+
7
+ # Raised when Neo4j.rb cannot find record by given id.
8
+ class RecordNotFound < Error
9
+ attr_reader :model, :primary_key, :id
10
+
11
+ def initialize(message = nil, model = nil, primary_key = nil, id = nil)
12
+ @primary_key = primary_key
13
+ @model = model
14
+ @id = id
15
+
16
+ super(message)
17
+ end
18
+ end
19
+
20
+ class DeprecatedSchemaDefinitionError < Error; end
21
+
22
+ class InvalidPropertyOptionsError < Error; end
23
+
24
+ class InvalidParameterError < Error; end
25
+
26
+ class UnknownTypeConverterError < Error; end
27
+
28
+ class DangerousAttributeError < ScriptError; end
29
+ class UnknownAttributeError < NoMethodError; end
30
+
31
+ class MigrationError < Error; end
32
+ class IrreversibleMigration < MigrationError; end
33
+ class UnknownMigrationVersionError < MigrationError; end
34
+
35
+ # Inspired/taken from active_record/migration.rb
36
+ class PendingMigrationError < MigrationError
37
+ def initialize(migrations)
38
+ pending_migrations = migrations.join("\n")
39
+ if rails? && defined?(Rails.env)
40
+ super("Migrations are pending:\n#{pending_migrations}\n To resolve this issue, run:\n\n #{command_name} neo4j:migrate RAILS_ENV=#{::Rails.env}")
41
+ else
42
+ super("Migrations are pending:\n#{pending_migrations}\n To resolve this issue, run:\n\n #{command_name} neo4j:migrate")
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def command_name
49
+ return 'rake' unless rails?
50
+ Rails.version.to_f >= 5 ? 'bin/rails' : 'bin/rake'
51
+ end
52
+
53
+ def rails?
54
+ defined?(Rails)
55
+ end
56
+ end
57
+
58
+ class Rollback < Error; end
59
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_model/attribute_set'
2
+
3
+ module ActiveGraph
4
+ class LazyAttributeHash < ActiveModel::LazyAttributeHash
5
+ def initialize(values, attr_list)
6
+ @types = {}
7
+ @values = {}
8
+ @additional_types = {}
9
+ @materialized = false
10
+ @delegate_hash = values
11
+
12
+ @default_attributes = process_default_attributes(attr_list)
13
+ end
14
+
15
+ private
16
+
17
+ def marshal_load(values)
18
+ initialize(values[4], values[3])
19
+ end
20
+
21
+ def process_default_attributes(attr_list)
22
+ if attr_list.is_a?(Hash)
23
+ attr_list
24
+ else
25
+ # initialize default attributes map with nil values
26
+ attr_list.each_with_object({}) do |name, map|
27
+ map[name] = nil
28
+ end
29
+ end
30
+ end
31
+
32
+ # we are using with_cast_value here because at the moment casting is being managed by
33
+ # Neo4j and not in ActiveModel
34
+ def assign_default_value(name)
35
+ delegate_hash[name] = ActiveModel::Attribute.with_cast_value(name, default_attributes[name].dup, nil)
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,148 @@
1
+ require 'benchmark'
2
+ require 'active_graph/migrations/helpers/id_property'
3
+
4
+ module ActiveGraph
5
+ class Migration
6
+ def migrate
7
+ fail 'not implemented'
8
+ end
9
+
10
+ def output(string = '')
11
+ puts string unless !!ENV['MIGRATIONS_SILENCED']
12
+ end
13
+
14
+ def print_output(string)
15
+ print string unless !!ENV['MIGRATIONS_SILENCED']
16
+ end
17
+
18
+ def default_path
19
+ Rails.root if defined? Rails
20
+ end
21
+
22
+ def joined_path(path)
23
+ File.join(path.to_s, 'db', 'neo4j-migrate')
24
+ end
25
+
26
+ def setup
27
+ FileUtils.mkdir_p('db/neo4j-migrate')
28
+ end
29
+
30
+ def query(*args)
31
+ ActiveGraph::Base.query(*args)
32
+ end
33
+
34
+ class AddIdProperty < ActiveGraph::Migration
35
+ include ActiveGraph::Migrations::Helpers::IdProperty
36
+
37
+ attr_reader :models_filename
38
+
39
+ def initialize(path = default_path)
40
+ @models_filename = File.join(joined_path(path), 'add_id_property.yml')
41
+ end
42
+
43
+ def migrate
44
+ ActiveSupport::Deprecation.warn '`AddIdProperty` task is deprecated and may be removed from future releases. '\
45
+ 'Create a new migration and use the `populate_id_property` helper.', caller
46
+ models = ActiveSupport::HashWithIndifferentAccess.new(YAML.load_file(models_filename))[:models]
47
+ output 'This task will add an ID Property every node in the given file.'
48
+ output 'It may take a significant amount of time, please be patient.'
49
+ models.each do |model|
50
+ output
51
+ output
52
+ output "Adding IDs to #{model}"
53
+ populate_id_property model
54
+ end
55
+ end
56
+
57
+ def query(*args)
58
+ Base.magic_query(*args)
59
+ end
60
+
61
+ def execute(*args)
62
+ Base.query(*args)
63
+ end
64
+
65
+ def setup
66
+ super
67
+ return if File.file?(models_filename)
68
+
69
+ File.open(models_filename, 'w') do |file|
70
+ message = <<MESSAGE
71
+ # Provide models to which IDs should be added.
72
+ # # It will only modify nodes that do not have IDs. There is no danger of overwriting data.
73
+ # # models: [Student,Lesson,Teacher,Exam]\nmodels: []
74
+ MESSAGE
75
+ file.write(message)
76
+ end
77
+ end
78
+
79
+ # Might need some of this...
80
+ # private
81
+
82
+ # def add_ids_to(model)
83
+ # max_per_batch = (ENV['MAX_PER_BATCH'] || default_max_per_batch).to_i
84
+
85
+ # label = model.mapped_label_name
86
+ # last_time_taken = nil
87
+
88
+ # until (nodes_left = idless_count(label, model.primary_key)) == 0
89
+ # print_status(last_time_taken, max_per_batch, nodes_left)
90
+
91
+ # count = [nodes_left, max_per_batch].min
92
+ # last_time_taken = Benchmark.realtime do
93
+ # max_per_batch = id_batch_set(label, model.primary_key, Array.new(count) { new_id_for(model) }, count)
94
+ # end
95
+ # end
96
+ # end
97
+
98
+ # def idless_count(label, id_property)
99
+ # ActiveGraph::Base.new_query.match(n: label).where("NOT EXISTS(n.#{id_property})").pluck('COUNT(n) AS ids').first
100
+ # end
101
+
102
+ # def print_status(last_time_taken, max_per_batch, nodes_left)
103
+ # time_per_node = last_time_taken / max_per_batch if last_time_taken
104
+ # message = if time_per_node
105
+ # eta_seconds = (nodes_left * time_per_node).round
106
+ # "#{nodes_left} nodes left. Last batch: #{(time_per_node * 1000.0).round(1)}ms / node (ETA: #{eta_seconds / 60} minutes)\r"
107
+ # else
108
+ # "Running first batch...\r"
109
+ # end
110
+
111
+ # print_output message
112
+ # end
113
+
114
+
115
+ # def id_batch_set(label, id_property, new_ids, count)
116
+ # tx = ActiveGraph::Base.new_transaction
117
+
118
+ # ActiveGraph::Base.query("MATCH (n:`#{label}`) WHERE NOT EXISTS(n.#{id_property})
119
+ # with COLLECT(n) as nodes, #{new_ids} as ids
120
+ # FOREACH(i in range(0,#{count - 1})|
121
+ # FOREACH(node in [nodes[i]]|
122
+ # SET node.#{id_property} = ids[i]))
123
+ # RETURN distinct(true)
124
+ # LIMIT #{count}")
125
+
126
+ # count
127
+ # rescue ActiveGraph::Server::CypherResponse::ResponseError, Faraday::TimeoutError
128
+ # new_max_per_batch = (max_per_batch * 0.8).round
129
+ # output "Error querying #{max_per_batch} nodes. Trying #{new_max_per_batch}"
130
+ # new_max_per_batch
131
+ # ensure
132
+ # tx.close
133
+ # end
134
+
135
+ # def default_max_per_batch
136
+ # 900
137
+ # end
138
+
139
+ # def new_id_for(model)
140
+ # if model.id_property_info[:type][:auto]
141
+ # SecureRandom.uuid
142
+ # else
143
+ # model.new.send(model.id_property_info[:type][:on])
144
+ # end
145
+ # end
146
+ end
147
+ end
148
+ end