3
3
module GraphQL
4
4
module Cache
5
5
module Resolvers
6
- # Pass cache write method into GraphQL::Relay::BaseConnection
7
- # and wrap them original Connection methods
8
6
class ConnectionResolver < BaseResolver
9
- class ConnectionCache < Module
7
+ NodesCache = Struct . new ( :nodes , :paged_nodes )
8
+
9
+ # Pass cache write method into GraphQL::Relay::RelationConnection
10
+ class RelationConnectionOverload < Module
10
11
module WrappedMethods
11
12
def paged_nodes
12
13
cache_write = instance_variable_get ( :@__cache_write )
13
14
14
- cache_write . call { super }
15
+ super . tap do |result |
16
+ # save original relation (aka @nodes) and loaded records
17
+ cache_write . call { NodesCache . new ( @nodes , result ) }
18
+ end
15
19
end
16
20
end
17
21
@@ -27,26 +31,43 @@ def extended(base)
27
31
28
32
def call ( args :, field :, parent :, context :, force_cache :)
29
33
if force_cache || ( cached = read ) . nil?
30
- define_connection_cache ( resolve_proc . call )
34
+ define_relation_cache ( resolve_proc . call )
31
35
else
32
36
wrap_connection ( cached , args , field , parent : parent , context : context )
33
37
end
34
38
end
35
39
36
40
private
37
41
38
- def wrap_connection ( value , args , field , **kwargs )
39
- GraphQL ::Relay ::BaseConnection . connection_for_nodes ( value ) . new (
40
- value ,
42
+ def wrap_connection ( cached , args , field , **kwargs )
43
+ nodes , paged_nodes = parse ( cached )
44
+
45
+ GraphQL ::Relay ::BaseConnection . connection_for_nodes ( nodes ) . new (
46
+ nodes ,
41
47
args ,
42
48
field : field ,
43
49
parent : kwargs [ :parent ] ,
44
50
context : kwargs [ :context ]
45
- )
51
+ ) . tap do |connection |
52
+ # restore cached paged_nodes
53
+ connection . instance_variable_set ( :@paged_nodes , paged_nodes ) if paged_nodes
54
+ end
55
+ end
56
+
57
+ def define_relation_cache ( connection )
58
+ if connection . is_a? ( GraphQL ::Relay ::RelationConnection )
59
+ # inject cached logic into the relation connection
60
+ connection . extend ( RelationConnectionOverload . new ( method ( :write ) ) )
61
+ else
62
+ # cache loaded connection (works for ArrayConnection)
63
+ write { connection }
64
+ end
46
65
end
47
66
48
- def define_connection_cache ( connection )
49
- connection . extend ( ConnectionCache . new ( method ( :write ) ) )
67
+ def parse ( cached )
68
+ return [ cached , nil ] unless cached . is_a? ( NodesCache )
69
+
70
+ [ cached . nodes , cached . paged_nodes ]
50
71
end
51
72
end
52
73
end
0 commit comments