find_cache 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,10 @@
1
- # FindCache
1
+ == FindCache
2
2
 
3
3
  It is simply an ActiveRecord object caching gem using Rails.cache methods.
4
4
 
5
- It makes ActiveRecord 'find_by_id, find_by_(attr)' methods and 'has_one, belongs_to relations' cacheable by id or any referenced columns using Rails.cache methods. It also supports fetching multiple records using ids with find_all_cache method(if cache store supports multiple reads [hint: memcached_store, dalli_store supports.]).
5
+ It makes "ActiveRecord 'find_by_id, find_by_(attr)' methods and 'has_one, belongs_to' relations" cacheable by id or any referenced columns using Rails.cache methods. It also supports fetching multiple records using ids with find_all_cache method(if cache store supports multiple reads [hint: memcached_store, dalli_store supports.]).
6
6
 
7
- ## Installation
7
+ == Installation
8
8
 
9
9
  Add this line to your application's Gemfile:
10
10
 
@@ -18,50 +18,44 @@ Or install it yourself as:
18
18
 
19
19
  $ gem install find_cache
20
20
 
21
- ## For has_one and belongs_to relations
21
+ == For has_one and belongs_to relations
22
22
 
23
23
  ### Sample Models:
24
24
 
25
- User (`has_one :user_detail`) ->
26
-
27
- find_cache_has_one :user_detail, UserDetail, :user_id
28
-
29
- find_cache_has_one attr_name_or_any_other_name, ModelName, foreign_key
30
-
31
- - name
32
- - email
33
- - username
34
-
35
- UserDetail (`belongs_to :user`) ->
36
-
37
- find_cache_belongs_to :user, User, :user_id
38
-
39
- find_cache_belongs_to attr_name_or_any_other_name, ModelName, foreign_key
25
+ class User < ActiveRecord::Base
26
+ has_one :user_detail
27
+
28
+ # to enable has_one caching
29
+ find_cache_has_one :user_detail, UserDetail, :user_id
30
+ end
40
31
 
41
- - user_id
42
- - avatar
43
- - age
44
- - sex
45
- - location
32
+ class UserDetail < ActiveRecord::Base
33
+ has_one :user_detail
34
+
35
+ # to enable belongs_to caching
36
+ find_cache_belongs_to :user, User, :user_id
37
+ end
46
38
 
47
- ## For finding a record
39
+ == For finding a record
48
40
 
49
41
  user = User.find_cache(id) # fetches from cache
50
- user.user_detail # fetches from cache if 'find_cache_has_one :user_detail, UserDetail, :user_id' added to User model
42
+ user.user_detail
43
+ # fetches from cache if the User model has
44
+ # 'find_cache_has_one :user_detail, UserDetail, :user_id'
51
45
 
52
46
  user = User.find_by_id(id) # fetches from DB
53
47
  user.user_detail # fetches from DB
54
48
 
55
- ## For fetching multiple ids
49
+ == For fetching multiple ids
56
50
 
57
51
  users = User.find_all_cache([1,2,3,4,5])
58
52
 
59
- ## For fetching a record by attribute
53
+ == For fetching a record by attribute
60
54
 
61
55
  user_detail = UserDetail.find_by_user_id(1) # from db
62
56
  user_detail = UserDetail.find_cache_by_ref(:user_id, 1) # from cache store
63
57
 
64
- ## For counter_cache 'cache invalidation'
58
+ == For counter_cache 'cache invalidation'
65
59
 
66
60
  ### Create a ruby file under config/initializers and add the following codes:
67
61
 
@@ -85,9 +79,10 @@ UserDetail (`belongs_to :user`) ->
85
79
  end
86
80
  end
87
81
 
88
- ## Notes
82
+ == Notes
89
83
 
90
84
  If your worker thread does not kill itself after execution you should clean the find_cache_store manually. It can be done simple in ApplicationController of your rails app adding this method as after_filter
85
+
91
86
  after_filter :clear_find_cache_store
92
87
 
93
88
  def clear_find_cache_store
@@ -96,11 +91,11 @@ If your worker thread does not kill itself after execution you should clean the
96
91
 
97
92
  Tested with dalli (https://github.com/mperham/dalli).
98
93
 
99
- ## Credits
94
+ == Credits
100
95
 
101
96
  FindCache is part of http://videofork.com project.
102
97
 
103
- ## Contributing
98
+ == Contributing
104
99
 
105
100
  1. Fork it
106
101
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -1,32 +1,59 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  module FindCache
3
+
4
+ # = FindCache Cachable
3
5
  module Cacheable
4
6
  extend ActiveSupport::Concern
5
7
 
6
- module ClassMethods
8
+ module ClassMethods
9
+ # has_one relational caching with find_cache
10
+ #
11
+ # ==== Parameters
12
+ #
13
+ # * +attribute+ - The attribute that you wish to name for cache
14
+ # * +model+ - The Model which data will be retreived for caching
15
+ # * +foreign_key+ - The FK attribute name in the given Model
16
+ #
17
+ # ==== Examples
18
+ #
19
+ # # For User model with user_id FroeignKey in UserDetail model
20
+ # find_cache_has_one :user_detail, UserDetail, :user_id
7
21
  def find_cache_has_one(attribute, model, foreign_key)
8
22
  send :define_method, attribute.to_sym do |*args|
9
23
  $find_cache_store[KeyGen.global_cache_key]["#{attribute}_#{model}_#{foreign_key}_#{self.id}"] ||= model.find_cache_by_ref(foreign_key, self.id)
10
24
  end
11
25
  end
12
26
 
27
+ # belongs_to relational caching with find_cache
28
+ #
29
+ # ==== Parameters
30
+ #
31
+ # * +attribute+ - The attribute that you wish to name for cache
32
+ # * +model+ - The Model which data will be retreived for caching
33
+ # * +foreign_key+ - The FK attribute name of given Model for the current Model
34
+ #
35
+ # ==== Examples
36
+ #
37
+ # # In UserDetail model with user_id FroeignKey of User model
38
+ # find_cache_belongs_to :user, User, :user_id
13
39
  def find_cache_belongs_to(attribute, model, foreign_key)
14
40
  send :define_method, attribute.to_sym do |*args|
15
41
  $find_cache_store[KeyGen.global_cache_key]["#{attribute}_#{model}_#{foreign_key}_#{self.send(foreign_key.to_sym)}"] ||= model.find_cache(self.send(foreign_key.to_sym))
16
42
  end
17
43
  end
18
- end
19
-
20
- included do
21
- after_commit :expire_find_cache
22
-
23
- def expire_find_cache
24
- key = KeyGen.cache_key(self.class.name, self.id)
25
- Rails.cache.delete(key)
26
- $find_cache_store[KeyGen.global_cache_key].delete(key)
27
- end
28
44
 
29
- def self.find_cache(id)
45
+ # To find an Active Record object using find_by_id method
46
+ # and caching it using Rails.cache methods
47
+ #
48
+ # ==== Parameters
49
+ #
50
+ # * +id+ - Id for the model
51
+ #
52
+ # ==== Examples
53
+ #
54
+ # # Find a User object with id 1 from User model
55
+ # User.find_cache(1)
56
+ def find_cache(id)
30
57
  key = KeyGen.cache_key(name, id)
31
58
  $find_cache_store[KeyGen.global_cache_key][key] ||= (
32
59
  Rails.cache.fetch(key) do
@@ -35,12 +62,24 @@ module FindCache
35
62
  )
36
63
  end
37
64
 
38
- def self.find_cache_by_ref(ref_attr, ref_id)
39
- key_ref = KeyGen.cache_key_ref(name, ref_attr, ref_id)
65
+ # To find an Active Record object using attributes other than
66
+ # primary key (:id) and caching it using Rails.cache methods
67
+ #
68
+ # ==== Parameters
69
+ #
70
+ # * +ref_attr+ - Reference attribute which will be looked in table
71
+ # * +ref_value+ - Value for the given referenced attribute
72
+ #
73
+ # ==== Examples
74
+ #
75
+ # # Find an UserDetail object using user_id attribute with value 1
76
+ # UserDetail.find_cache_by_ref(:user_id, 1)
77
+ def find_cache_by_ref(ref_attr, ref_val)
78
+ key_ref = KeyGen.cache_key_ref(name, ref_attr, ref_val)
40
79
  if (id = Rails.cache.read(key_ref))
41
80
  find_cache(id)
42
81
  else
43
- item = send("find_by_#{ref_attr}", "#{ref_id}")
82
+ item = send("find_by_#{ref_attr}", "#{ref_val}")
44
83
  if item
45
84
  Rails.cache.write(key_ref, item.id)
46
85
  Rails.cache.write(KeyGen.cache_key(name, item.id), item)
@@ -49,10 +88,27 @@ module FindCache
49
88
  end
50
89
  end
51
90
 
52
- def self.find_all_cache(ids, order_by = "id DESC")
91
+
92
+ # To find all Active Record objects using id list
93
+ #
94
+ # ==== Parameters
95
+ #
96
+ # * +ids+ - List of ids
97
+ # * +order_by+ - optional order direction for results
98
+ #
99
+ # ==== Notes
100
+ # # Only valid if the Rails.cache store supports read_multi
101
+ #
102
+ # ==== Examples
103
+ #
104
+ # # Find users with ids ([21, 1, 2, 19, 43]) from User model
105
+ # UserDetail.find_all_cache([21, 1, 2, 19, 43])
106
+ # # Find users with ids ([21, 1, 2, 19, 43]) and id ASC
107
+ # UserDetail.find_all_cache(([21, 1, 2, 19, 43]), "id ASC")
108
+ def find_all_cache(ids, order_by = "id DESC")
53
109
  all_new_cache = []
54
110
  not_in_cache = []
55
- cache_ids = generate_cache_keys(ids)
111
+ cache_ids = ids.map { |id| KeyGen.cache_key(name, id) }
56
112
  all_cache = Rails.cache.read_multi(cache_ids)
57
113
  cache_ids.each_with_index do |cache_id, cache_id_index|
58
114
  if all_cache[cache_id]
@@ -71,14 +127,16 @@ module FindCache
71
127
  all_new_cache.each do |cached_item|
72
128
  $find_cache_store[KeyGen.global_cache_key][KeyGen.cache_key(name, cached_item.id)] = cached_item
73
129
  end
74
- end
75
-
76
- def self.generate_cache_keys(ids)
77
- cache_ids = []
78
- ids.each do |id|
79
- cache_ids << KeyGen.cache_key(name, id)
80
- end
81
- cache_ids
130
+ end
131
+ end
132
+
133
+ included do
134
+ after_commit :expire_find_cache
135
+
136
+ def expire_find_cache
137
+ key = KeyGen.cache_key(self.class.name, self.id)
138
+ Rails.cache.delete(key)
139
+ $find_cache_store[KeyGen.global_cache_key].delete(key)
82
140
  end
83
141
  end
84
142
  end
@@ -1,2 +1,3 @@
1
1
  # -*- encoding: utf-8 -*-
2
+ # A local cache store for cached objects of Threads
2
3
  $find_cache_store = {}
@@ -3,15 +3,48 @@ module FindCache
3
3
  class KeyGen
4
4
  require "simple_uuid"
5
5
 
6
+ # cache_key generator for model items
7
+ #
8
+ # ==== Parameters
9
+ #
10
+ # * +model_name+ - The name of the model
11
+ # * +id+ - Id for the given model
12
+ #
13
+ # ==== Examples
14
+ #
15
+ # FindCache::KeyGen.cache_key("User", 1)
6
16
  def self.cache_key(model_name, id)
7
17
  "#{model_name}/#{id}"
8
18
  end
9
19
 
20
+ # cache_key generator for model items with referenced attribute
21
+ #
22
+ # ==== Parameters
23
+ #
24
+ # * +model_name+ - The name of the model
25
+ # * +foreign_key_name+ - Name of the foreign_key attribute
26
+ # * +foreign_key_id+ - Id for the given foreign_key name
27
+ #
28
+ # ==== Examples
29
+ #
30
+ # FindCache::KeyGen.cache_key_ref("UserDetail", "user_id", 1)
10
31
  def self.cache_key_ref(model_name, foreign_key_name, foreign_key_id)
11
32
  "#{model_name}/#{foreign_key_name}-#{foreign_key_id}"
12
33
  end
13
34
 
14
- def self.global_cache_key(clear=false)
35
+ # cache_key generator for the current thread
36
+ #
37
+ # ==== Parameters
38
+ #
39
+ # * +clear+ - Boolean value to clean up the current Thread's cache key
40
+ #
41
+ # ==== Examples
42
+ #
43
+ # # For generating cache key for the current Thread
44
+ # FindCache::KeyGen.global_cache_key
45
+ # # For cleaning generated cache key for the current Thread
46
+ # FindCache::KeyGen.global_cache_key(true)
47
+ def self.global_cache_key(clear = false)
15
48
  return (Thread.current[:global_cache_key] = nil) if clear
16
49
  Thread.current[:global_cache_key] ||= (
17
50
  t = SimpleUUID::UUID.new(Time.now).to_i.to_s(16).rjust(32, "0")
@@ -20,6 +53,8 @@ module FindCache
20
53
  )
21
54
  end
22
55
 
56
+ # Cleaning all caches of the current Thread not the Rails.cache
57
+ #
23
58
  def self.clear_find_cache_store
24
59
  $find_cache_store.delete(KeyGen.global_cache_key)
25
60
  KeyGen.global_cache_key(true)
@@ -1,4 +1,4 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  module FindCache
3
- VERSION = "0.1.6"
3
+ VERSION = "0.1.7"
4
4
  end
Binary file
@@ -375,3 +375,54 @@ Connecting to database specified by database.yml
375
375
  User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 9 LIMIT 1
376
376
  User Load (0.3ms) SELECT "users".* FROM "users" LIMIT 1
377
377
  Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = 1 LIMIT 1
378
+ Connecting to database specified by database.yml
379
+ Post Load (0.2ms) SELECT "posts".* FROM "posts" LIMIT 1
380
+  (0.1ms) begin transaction
381
+ SQL (6.2ms) INSERT INTO "comments" ("content", "created_at", "post_id", "updated_at") VALUES (?, ?, ?, ?) [["content", "test content for comment"], ["created_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00], ["post_id", 1], ["updated_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00]]
382
+ Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
383
+ SQL (0.2ms) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1 WHERE "posts"."id" = 1
384
+  (1.5ms) commit transaction
385
+ Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
386
+ Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
387
+ Post Load (0.2ms) SELECT "posts".* FROM "posts" LIMIT 1
388
+  (0.0ms) begin transaction
389
+ SQL (0.4ms) INSERT INTO "comments" ("content", "created_at", "post_id", "updated_at") VALUES (?, ?, ?, ?) [["content", "test 1 content for comment"], ["created_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00], ["post_id", 1], ["updated_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00]]
390
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
391
+ SQL (0.1ms) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1 WHERE "posts"."id" = 1
392
+  (1.6ms) commit transaction
393
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" LIMIT 1
394
+  (0.0ms) begin transaction
395
+ SQL (0.3ms) INSERT INTO "comments" ("content", "created_at", "post_id", "updated_at") VALUES (?, ?, ?, ?) [["content", "test 2 content for comment"], ["created_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00], ["post_id", 1], ["updated_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00]]
396
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
397
+ SQL (0.1ms) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1 WHERE "posts"."id" = 1
398
+  (1.4ms) commit transaction
399
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" LIMIT 1
400
+  (0.0ms) begin transaction
401
+ SQL (0.4ms) INSERT INTO "comments" ("content", "created_at", "post_id", "updated_at") VALUES (?, ?, ?, ?) [["content", "test 3 content for comment"], ["created_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00], ["post_id", 1], ["updated_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00]]
402
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
403
+ SQL (0.1ms) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1 WHERE "posts"."id" = 1
404
+  (1.5ms) commit transaction
405
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" LIMIT 1
406
+  (0.0ms) begin transaction
407
+ SQL (0.3ms) INSERT INTO "comments" ("content", "created_at", "post_id", "updated_at") VALUES (?, ?, ?, ?) [["content", "test 4 content for comment"], ["created_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00], ["post_id", 1], ["updated_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00]]
408
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
409
+ SQL (0.1ms) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1 WHERE "posts"."id" = 1
410
+  (1.8ms) commit transaction
411
+ Comment Load (0.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."id" IN (32, 33, 34, 35) ORDER BY id ASC
412
+ Comment Load (0.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."id" IN (32, 33, 34, 35) ORDER BY id ASC
413
+ Post Load (0.2ms) SELECT "posts".* FROM "posts" LIMIT 1
414
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
415
+  (0.1ms) begin transaction
416
+  (0.1ms) commit transaction
417
+ Post Load (0.2ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = 1 LIMIT 1
418
+ Post Load (0.3ms) SELECT "posts".* FROM "posts" LIMIT 1
419
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 LIMIT 1
420
+  (0.1ms) begin transaction
421
+ SQL (0.6ms) INSERT INTO "users" ("created_at", "email", "password", "updated_at") VALUES (?, ?, ?, ?) [["created_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00], ["email", "test@videofork.com"], ["password", "test1234"], ["updated_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00]]
422
+ SQL (0.4ms) INSERT INTO "posts" ("body", "comments_count", "created_at", "title", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?) [["body", nil], ["comments_count", nil], ["created_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00], ["title", nil], ["updated_at", Wed, 29 Aug 2012 18:30:29 UTC +00:00], ["user_id", 10]]
423
+ Post Load (0.1ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = 10 LIMIT 1
424
+  (1.8ms) commit transaction
425
+ User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = 10 LIMIT 1
426
+ User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 10 LIMIT 1
427
+ User Load (0.3ms) SELECT "users".* FROM "users" LIMIT 1
428
+ Post Load (0.3ms) SELECT "posts".* FROM "posts" WHERE "posts"."user_id" = 1 LIMIT 1
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: find_cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-29 00:00:00.000000000 Z
12
+ date: 2012-08-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -186,6 +186,7 @@ files:
186
186
  - test/dummy/tmp/cache/276/5C0/User%2F9
187
187
  - test/dummy/tmp/cache/276/6F0/Post%2F2
188
188
  - test/dummy/tmp/cache/277/700/Post%2F3
189
+ - test/dummy/tmp/cache/29E/F20/User%2F10
189
190
  - test/dummy/tmp/cache/3A8/070/Comment%2F7
190
191
  - test/dummy/tmp/cache/3A9/080/Comment%2F8
191
192
  - test/dummy/tmp/cache/3AA/090/Comment%2F9
@@ -197,10 +198,14 @@ files:
197
198
  - test/dummy/tmp/cache/3D5/D70/Comment%2F22
198
199
  - test/dummy/tmp/cache/3D6/D70/Comment%2F14
199
200
  - test/dummy/tmp/cache/3D6/D80/Comment%2F23
201
+ - test/dummy/tmp/cache/3D6/D90/Comment%2F32
200
202
  - test/dummy/tmp/cache/3D7/D80/Comment%2F15
201
203
  - test/dummy/tmp/cache/3D7/D90/Comment%2F24
204
+ - test/dummy/tmp/cache/3D7/DA0/Comment%2F33
202
205
  - test/dummy/tmp/cache/3D8/DA0/Comment%2F25
206
+ - test/dummy/tmp/cache/3D8/DB0/Comment%2F34
203
207
  - test/dummy/tmp/cache/3D9/DA0/Comment%2F17
208
+ - test/dummy/tmp/cache/3D9/DC0/Comment%2F35
204
209
  - test/dummy/tmp/cache/3DA/DB0/Comment%2F18
205
210
  - test/dummy/tmp/cache/3DA/DC0/Comment%2F27
206
211
  - test/dummy/tmp/cache/3DB/DC0/Comment%2F19
@@ -292,6 +297,7 @@ test_files:
292
297
  - test/dummy/tmp/cache/276/5C0/User%2F9
293
298
  - test/dummy/tmp/cache/276/6F0/Post%2F2
294
299
  - test/dummy/tmp/cache/277/700/Post%2F3
300
+ - test/dummy/tmp/cache/29E/F20/User%2F10
295
301
  - test/dummy/tmp/cache/3A8/070/Comment%2F7
296
302
  - test/dummy/tmp/cache/3A9/080/Comment%2F8
297
303
  - test/dummy/tmp/cache/3AA/090/Comment%2F9
@@ -303,10 +309,14 @@ test_files:
303
309
  - test/dummy/tmp/cache/3D5/D70/Comment%2F22
304
310
  - test/dummy/tmp/cache/3D6/D70/Comment%2F14
305
311
  - test/dummy/tmp/cache/3D6/D80/Comment%2F23
312
+ - test/dummy/tmp/cache/3D6/D90/Comment%2F32
306
313
  - test/dummy/tmp/cache/3D7/D80/Comment%2F15
307
314
  - test/dummy/tmp/cache/3D7/D90/Comment%2F24
315
+ - test/dummy/tmp/cache/3D7/DA0/Comment%2F33
308
316
  - test/dummy/tmp/cache/3D8/DA0/Comment%2F25
317
+ - test/dummy/tmp/cache/3D8/DB0/Comment%2F34
309
318
  - test/dummy/tmp/cache/3D9/DA0/Comment%2F17
319
+ - test/dummy/tmp/cache/3D9/DC0/Comment%2F35
310
320
  - test/dummy/tmp/cache/3DA/DB0/Comment%2F18
311
321
  - test/dummy/tmp/cache/3DA/DC0/Comment%2F27
312
322
  - test/dummy/tmp/cache/3DB/DC0/Comment%2F19