@@ -7,49 +7,50 @@ class ArgumentsCache
7
7
def initialize ( query )
8
8
@query = query
9
9
@dataloader = query . context . dataloader
10
- @storage = Hash . new do |h , ast_node |
11
- h [ ast_node ] = Hash . new do |h2 , arg_owner |
12
- h2 [ arg_owner ] = Hash . new do |h3 , parent_object |
13
- dataload_for ( ast_node , arg_owner , parent_object ) do |kwarg_arguments |
14
- h3 [ parent_object ] = @query . after_lazy ( kwarg_arguments ) do |resolved_args |
15
- h3 [ parent_object ] = resolved_args
16
- end
17
- end
18
-
19
- if !h3 . key? ( parent_object )
20
- # TODO should i bother putting anything here?
21
- h3 [ parent_object ] = NO_ARGUMENTS
22
- else
23
- h3 [ parent_object ]
24
- end
10
+ @storage = Hash . new do |h , argument_owner |
11
+ args_by_parent = if argument_owner . arguments_statically_coercible?
12
+ shared_values_cache = { }
13
+ Hash . new do |h2 , ignored_parent_object |
14
+ h2 [ ignored_parent_object ] = shared_values_cache
15
+ end
16
+ else
17
+ Hash . new do |h2 , parent_object |
18
+ args_by_node = { }
19
+ args_by_node . compare_by_identity
20
+ h2 [ parent_object ] = args_by_node
25
21
end
26
22
end
23
+ args_by_parent . compare_by_identity
24
+ h [ argument_owner ] = args_by_parent
27
25
end
26
+ @storage . compare_by_identity
28
27
end
29
28
30
29
def fetch ( ast_node , argument_owner , parent_object )
31
- # If any jobs were enqueued, run them now,
32
- # since this might have been called outside of execution.
33
- # (The jobs are responsible for updating `result` in-place. )
34
- if ! @storage . key? ( ast_node ) || ! @storage [ ast_node ] . key? ( argument_owner )
35
- @dataloader . run_isolated do
36
- @storage [ ast_node ] [ argument_owner ] [ parent_object ]
30
+ # This runs eagerly if no block is given
31
+ @storage [ argument_owner ] [ parent_object ] [ ast_node ] ||= begin
32
+ args_hash = self . class . prepare_args_hash ( @query , ast_node )
33
+ kwarg_arguments = argument_owner . coerce_arguments ( parent_object , args_hash , @query . context )
34
+ @query . after_lazy ( kwarg_arguments ) do | resolved_args |
35
+ @storage [ argument_owner ] [ parent_object ] [ ast_node ] = resolved_args
37
36
end
38
37
end
39
- # Ack, the _hash_ is updated, but the key is eventually
40
- # overridden with an immutable arguments instance.
41
- # The first call queues up the job,
42
- # then this call fetches the result.
43
- # TODO this should be better, find a solution
44
- # that works with merging the runtime.rb code
45
- @storage [ ast_node ] [ argument_owner ] [ parent_object ]
38
+
46
39
end
47
40
48
41
# @yield [Interpreter::Arguments, Lazy<Interpreter::Arguments>] The finally-loaded arguments
49
42
def dataload_for ( ast_node , argument_owner , parent_object , &block )
50
43
# First, normalize all AST or Ruby values to a plain Ruby hash
51
- args_hash = self . class . prepare_args_hash ( @query , ast_node )
52
- argument_owner . coerce_arguments ( parent_object , args_hash , @query . context , &block )
44
+ arg_storage = @storage [ argument_owner ] [ parent_object ]
45
+ if ( args = arg_storage [ ast_node ] )
46
+ yield ( args )
47
+ else
48
+ args_hash = self . class . prepare_args_hash ( @query , ast_node )
49
+ argument_owner . coerce_arguments ( parent_object , args_hash , @query . context ) do |resolved_args |
50
+ arg_storage [ ast_node ] = resolved_args
51
+ yield ( resolved_args )
52
+ end
53
+ end
53
54
nil
54
55
end
55
56
0 commit comments