delfos 0.0.2.pre.rc2 → 0.0.2.pre.rc3

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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/exe/delfos_import +38 -0
  3. data/exe/delfos_import_offline_queries +9 -0
  4. data/exe/delfos_update_distance +11 -0
  5. data/lib/delfos.rb +29 -73
  6. data/lib/delfos/config.rb +90 -0
  7. data/lib/delfos/config/inclusion.rb +90 -0
  8. data/lib/delfos/file_system.rb +7 -2
  9. data/lib/delfos/file_system/app_directories.rb +16 -18
  10. data/lib/delfos/file_system/app_files.rb +31 -0
  11. data/lib/delfos/file_system/file_cache.rb +21 -0
  12. data/lib/delfos/file_system/path_determination.rb +10 -7
  13. data/lib/delfos/method_trace.rb +18 -6
  14. data/lib/delfos/method_trace/call_handler.rb +6 -2
  15. data/lib/delfos/method_trace/code_location.rb +2 -12
  16. data/lib/delfos/method_trace/code_location/container_method_factory.rb +50 -25
  17. data/lib/delfos/method_trace/code_location/eval_in_caller.rb +2 -4
  18. data/lib/delfos/method_trace/code_location/filename_helpers.rb +1 -1
  19. data/lib/delfos/method_trace/code_location/method.rb +13 -9
  20. data/lib/delfos/neo4j.rb +12 -3
  21. data/lib/delfos/neo4j/distance/update.rb +1 -1
  22. data/lib/delfos/neo4j/live/call_site_logger.rb +27 -0
  23. data/lib/delfos/neo4j/offline.rb +13 -0
  24. data/lib/delfos/neo4j/offline/call_site_logger.rb +6 -1
  25. data/lib/delfos/neo4j/offline/importer.rb +8 -7
  26. data/lib/delfos/neo4j/query_execution/batch/execution.rb +93 -0
  27. data/lib/delfos/neo4j/query_execution/batch/retryable.rb +103 -0
  28. data/lib/delfos/neo4j/query_execution/errors.rb +4 -3
  29. data/lib/delfos/neo4j/query_execution/http.rb +1 -1
  30. data/lib/delfos/neo4j/query_execution/sync.rb +1 -1
  31. data/lib/delfos/neo4j/query_execution/transactional.rb +1 -1
  32. data/lib/delfos/neo4j/schema.rb +1 -1
  33. metadata +38 -16
  34. data/lib/delfos/neo4j/batch/execution.rb +0 -91
  35. data/lib/delfos/neo4j/batch/retryable.rb +0 -101
  36. data/lib/delfos/setup.rb +0 -120
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "file_cache"
4
+
5
+ module Delfos
6
+ module FileSystem
7
+ class AppFiles
8
+ include FileCache
9
+
10
+ def initialize(included, excluded)
11
+ @included = included
12
+ @excluded = excluded
13
+ end
14
+
15
+ def include?(file)
16
+ !exclude?(file)
17
+ end
18
+
19
+ def exclude?(file)
20
+ return false if file.nil?
21
+ with_cache(file) { should_exclude?(file) }
22
+ end
23
+
24
+ private
25
+
26
+ def should_exclude?(file)
27
+ @excluded.include?(Pathname(file).expand_path)
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Delfos
4
+ module FileSystem
5
+ module FileCache
6
+ def reset!
7
+ @cache = nil
8
+ end
9
+
10
+ private
11
+
12
+ def with_cache(key)
13
+ cache.include?(key) ? cache[key] : cache[key] = yield
14
+ end
15
+
16
+ def cache
17
+ @cache ||= {}
18
+ end
19
+ end
20
+ end
21
+ end
@@ -15,18 +15,21 @@ module Delfos
15
15
 
16
16
  def full_path
17
17
  return @file.realpath if Pathname.new(@file).exist?
18
-
19
- Delfos.application_directories.map do |d|
20
- path = try_path { d + @file }
21
-
22
- path || try_path do
23
- Pathname.new(d + @file.to_s.gsub(%r{[^/]*/}, ""))
24
- end
18
+ Delfos.config.included_directories.map do |d|
19
+ determine_path(d)
25
20
  end.compact.first
26
21
  end
27
22
 
28
23
  private
29
24
 
25
+ def determine_path(d)
26
+ path = try_path { d + @file }
27
+
28
+ path || try_path do
29
+ Pathname.new(d + @file.to_s.gsub(%r{[^/]*/}, ""))
30
+ end
31
+ end
32
+
30
33
  def strip_block_message(f)
31
34
  f.to_s.split(" in block").first
32
35
  end
@@ -6,7 +6,24 @@ require_relative "call_stack"
6
6
  module Delfos
7
7
  module MethodTrace
8
8
  class << self
9
- def trace!
9
+ def enable!
10
+ method_trace.perform
11
+ end
12
+
13
+ def disable!
14
+ @method_trace&.disable!
15
+ @method_trace = nil
16
+ end
17
+
18
+ private
19
+
20
+ def method_trace
21
+ @method_trace ||= Setup.new
22
+ end
23
+ end
24
+
25
+ class Setup
26
+ def perform
10
27
  on_call.enable
11
28
  on_return.enable
12
29
  @last_returned = nil
@@ -14,12 +31,7 @@ module Delfos
14
31
 
15
32
  def disable!
16
33
  @on_call&.disable
17
- @on_call = nil
18
-
19
34
  @on_return&.disable
20
- @on_return = nil
21
-
22
- @last_returned = nil
23
35
  end
24
36
 
25
37
  def on_call
@@ -2,14 +2,14 @@
2
2
 
3
3
  require "delfos/call_stack"
4
4
  require_relative "code_location"
5
- require_relative "code_location/filename_helpers"
5
+ require_relative "code_location/eval_in_caller"
6
6
 
7
7
  module Delfos
8
8
  module MethodTrace
9
9
  CallHandler = Struct.new(:trace_point)
10
10
 
11
11
  class CallHandler
12
- include CodeLocation::FilenameHelpers
12
+ include CodeLocation::EvalInCaller
13
13
 
14
14
  def perform
15
15
  return unless relevant?
@@ -17,8 +17,12 @@ module Delfos
17
17
  CallStack.push(call_site)
18
18
  end
19
19
 
20
+ STACK_OFFSET = 7
21
+
20
22
  def call_site
21
23
  @call_site ||= CodeLocation.callsite_from(
24
+ file: eval_in_caller("__FILE__", STACK_OFFSET),
25
+ line_number: eval_in_caller("__LINE__", STACK_OFFSET),
22
26
  container_method: container_method,
23
27
  called_method: called_method,
24
28
  )
@@ -3,27 +3,17 @@
3
3
  require_relative "code_location/method"
4
4
  require_relative "code_location/call_site"
5
5
  require_relative "code_location/container_method_factory"
6
- require_relative "code_location/eval_in_caller"
7
6
 
8
7
  module Delfos
9
8
  module MethodTrace
10
9
  module CodeLocation
11
10
  class << self
12
- include EvalInCaller
13
-
14
11
  def method_from(attrs)
15
12
  Method.new(attrs)
16
13
  end
17
14
 
18
- STACK_OFFSET = 8
19
-
20
- def callsite_from(container_method:, called_method:, stack_offset: STACK_OFFSET)
21
- CallSite.new(
22
- container_method: container_method,
23
- called_method: called_method,
24
- file: eval_in_caller("__FILE__", stack_offset),
25
- line_number: eval_in_caller("__LINE__", stack_offset),
26
- )
15
+ def callsite_from(attrs)
16
+ CallSite.new(attrs)
27
17
  end
28
18
 
29
19
  def create_container_method
@@ -9,7 +9,9 @@ module Delfos
9
9
  class ContainerMethodFactory
10
10
  include EvalInCaller
11
11
  include FilenameHelpers
12
+
12
13
  STACK_OFFSET = 12
14
+
13
15
  attr_reader :stack_offset
14
16
 
15
17
  def self.create(stack_offset: STACK_OFFSET)
@@ -21,49 +23,72 @@ module Delfos
21
23
  end
22
24
 
23
25
  def create
24
- # ensure evaluated and memoised with correct stack offset
25
- class_method
26
-
27
- CodeLocation.method_from(
28
- object: object,
29
- method_name: meth,
30
- file: file,
31
- line_number: line,
32
- class_method: class_method,
33
- )
26
+ # ensure memoised with correct stack offset
27
+ method_object
28
+ source_location
29
+
30
+ CodeLocation.method_from(attrs)
34
31
  end
35
32
 
36
33
  private
37
34
 
38
- def object
39
- @object ||= eval_in_caller("self", stack_offset)
35
+ def attrs
36
+ {
37
+ object: object,
38
+ method_name: method_name,
39
+ file: file,
40
+ line_number: line,
41
+ class_method: class_method,
42
+ method_object: method_object,
43
+ super_method: super_method,
44
+ }
40
45
  end
41
46
 
42
47
  def class_method
43
48
  return @class_method if defined?(@class_method)
44
49
 
45
- @class_method = eval_in_caller("is_a?(Module)", STACK_OFFSET)
50
+ @class_method = object.is_a?(Module)
46
51
  end
47
52
 
48
- RUBY_IS_MAIN = "self.class == Object && self&.to_s == 'main' && __method__.nil?"
49
- RUBY_SOURCE_LOCATION = "(__method__).source_location if __method__"
50
- RUBY_CLASS_METHOD_SOURCE = "method#{RUBY_SOURCE_LOCATION}"
51
- RUBY_INSTANCE_METHOD_SOURCE = "self.class.instance_method#{RUBY_SOURCE_LOCATION}"
53
+ def file
54
+ return @file if defined? @file
52
55
 
53
- def method_finder
54
- @method_finder ||= class_method ? RUBY_CLASS_METHOD_SOURCE : RUBY_INSTANCE_METHOD_SOURCE
56
+ @file = source_location&.first
55
57
  end
56
58
 
57
- def file
58
- @file ||= eval_in_caller("(#{RUBY_IS_MAIN}) ? __FILE__ : ((#{method_finder})&.first)", stack_offset)
59
+ def line
60
+ return @line if defined? @line
61
+
62
+ @line = source_location&.last
59
63
  end
60
64
 
61
- def line
62
- @line ||= eval_in_caller("(#{RUBY_IS_MAIN}) ? __LINE__ : ((#{method_finder})&.last)", stack_offset)
65
+ def source_location
66
+ return @source_location if defined? @source_location
67
+
68
+ @source_location =
69
+ method_object&.source_location ||
70
+ eval_in_caller("[__FILE__, __LINE__]", stack_offset)
63
71
  end
64
72
 
65
- def meth
66
- @meth ||= eval_in_caller("__method__", stack_offset)
73
+ REPRESENTATION_OF_MAIN = Object.new
74
+
75
+ def object
76
+ @object ||= method_object&.receiver || REPRESENTATION_OF_MAIN
77
+ end
78
+
79
+ def method_name
80
+ @method_name ||= method_object&.name
81
+ end
82
+
83
+ def super_method
84
+ method_object&.super_method
85
+ end
86
+
87
+ RUBY_METHOD = "method(__method__) if __method__"
88
+
89
+ def method_object
90
+ return @method_object if defined? @method_object
91
+ @method_object = eval_in_caller(RUBY_METHOD, stack_offset)
67
92
  end
68
93
  end
69
94
  end
@@ -6,10 +6,8 @@ module Delfos
6
6
  module MethodTrace
7
7
  module CodeLocation
8
8
  module EvalInCaller
9
- def eval_in_caller(s, offset, &block)
10
- other = binding.of_caller(offset)
11
-
12
- other.eval(s)
9
+ def eval_in_caller(s, offset)
10
+ binding.of_caller(offset).eval(s)
13
11
  end
14
12
  end
15
13
  end
@@ -22,7 +22,7 @@ module Delfos
22
22
  return unless f
23
23
  file = f.to_s
24
24
 
25
- Delfos.application_directories.map do |d|
25
+ Delfos.config.included_directories.map do |d|
26
26
  file = relative_path(file, d)
27
27
  end
28
28
 
@@ -7,15 +7,19 @@ module Delfos
7
7
  module CodeLocation
8
8
  class Method
9
9
  include FilenameHelpers
10
- attr_reader :object, :line_number, :class_method
11
-
12
- def initialize(object:, method_name:, file:, line_number:, class_method:)
13
- @object = object
14
- @method_name = method_name
15
- @file = file
16
- @line_number = line_number
17
- @class_method = class_method
18
- end
10
+ attr_reader :object, :line_number, :class_method, :method_object, :super_method
11
+
12
+ # rubocop:disable Metrics/ParameterLists
13
+ def initialize(object:, method_name:, file:, line_number:, class_method:, method_object: nil, super_method: nil)
14
+ @object = object
15
+ @method_name = method_name
16
+ @file = file
17
+ @line_number = line_number
18
+ @class_method = class_method
19
+ @method_object = method_object
20
+ @super_method = super_method
21
+ end
22
+ # rubocop:enable Metrics/ParameterLists
19
23
 
20
24
  def klass_name
21
25
  klass.name
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "neo4j/query_execution/sync"
4
- require_relative "neo4j/batch/retryable"
4
+ require_relative "neo4j/query_execution/batch/retryable"
5
5
  require_relative "neo4j/schema"
6
6
  require_relative "neo4j/distance/update"
7
+ require_relative "neo4j/offline"
7
8
 
8
9
  module Delfos
9
10
  module Neo4j
@@ -14,11 +15,15 @@ module Delfos
14
15
  end
15
16
 
16
17
  def execute(query, params = {})
17
- Batch::Retryable.execute!(query, params: params, size: Delfos.batch_size)
18
+ QueryExecution::Batch::Retryable.execute!(query, params: params, size: Delfos.batch_size)
18
19
  end
19
20
 
20
21
  def flush!
21
- Batch::Retryable.flush!
22
+ QueryExecution::Batch::Retryable.flush!
23
+ end
24
+
25
+ def reset!
26
+ Delfos::Neo4j::QueryExecution::Batch::Retryable.reset!
22
27
  end
23
28
 
24
29
  def ensure_schema!
@@ -28,6 +33,10 @@ module Delfos
28
33
  )
29
34
  end
30
35
 
36
+ def import_offline_queries(filename)
37
+ Offline.import_queries(filename)
38
+ end
39
+
31
40
  def update_distance!
32
41
  Distance::Update.new.perform
33
42
  end
@@ -9,7 +9,7 @@ module Delfos
9
9
  class Update
10
10
  def perform
11
11
  results = CallSiteFetcher.perform
12
- return if results.length.negative?
12
+ return unless results.length.positive?
13
13
 
14
14
  results.each do |start_file, call_site_id, finish_file, called_id|
15
15
  handle(start_file, call_site_id, finish_file, called_id)
@@ -11,6 +11,33 @@ module Delfos
11
11
 
12
12
  Neo4j.execute(q.query, q.params)
13
13
  end
14
+
15
+ def finish!
16
+ reset_call_stack!
17
+ update_distance!
18
+ end
19
+
20
+ def reset!
21
+ reset_call_stack!
22
+ Neo4j.reset!
23
+ end
24
+
25
+ private
26
+
27
+ def flush!
28
+ Neo4j.flush!
29
+ end
30
+
31
+ def update_distance!
32
+ Neo4j.update_distance!
33
+ flush!
34
+ end
35
+
36
+ def reset_call_stack!
37
+ Delfos::CallStack.pop_until_top!
38
+ Delfos::CallStack.reset!
39
+ flush!
40
+ end
14
41
  end
15
42
  end
16
43
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "offline/importer"
4
+
5
+ module Delfos
6
+ module Neo4j
7
+ module Offline
8
+ def self.import_queries(filename)
9
+ Importer.new(filename).perform
10
+ end
11
+ end
12
+ end
13
+ end
@@ -17,11 +17,16 @@ module Delfos
17
17
  file.flush if (count % 100).zero?
18
18
  end
19
19
 
20
+ def reset!
21
+ finish!
22
+ end
23
+
20
24
  def finish!
21
- return if file.closed?
25
+ return if Delfos.offline_query_filename.nil? || file.closed?
22
26
 
23
27
  file.flush
24
28
  file.close
29
+ @file = nil
25
30
  end
26
31
 
27
32
  def count