
Added AttachmentCache
@0844910716b1127aab2c918ddf9190a23d0d64ea
--- app/models/Attachment.java
+++ app/models/Attachment.java
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 |
*/ |
21 | 21 |
package models; |
22 | 22 |
|
23 |
+import utils.AttachmentCache; |
|
23 | 24 |
import controllers.AttachmentApp; |
24 | 25 |
import models.enumeration.ResourceType; |
25 | 26 |
import models.resource.GlobalResource; |
... | ... | @@ -108,9 +109,16 @@ |
108 | 109 |
*/ |
109 | 110 |
public static List<Attachment> findByContainer( |
110 | 111 |
ResourceType containerType, String containerId) { |
111 |
- return find.where() |
|
112 |
+ List<Attachment> cachedData = AttachmentCache.get(containerType, containerId); |
|
113 |
+ if (cachedData != null) { |
|
114 |
+ return cachedData; |
|
115 |
+ } |
|
116 |
+ |
|
117 |
+ List<Attachment> list = find.where() |
|
112 | 118 |
.eq("containerType", containerType) |
113 | 119 |
.eq("containerId", containerId).findList(); |
120 |
+ AttachmentCache.set(containerType.name() + containerId, list); |
|
121 |
+ return list; |
|
114 | 122 |
} |
115 | 123 |
|
116 | 124 |
/** |
... | ... | @@ -120,7 +128,14 @@ |
120 | 128 |
* @return attachments of the container |
121 | 129 |
*/ |
122 | 130 |
public static List<Attachment> findByContainer(Resource container) { |
123 |
- return findByContainer(container.getType(), container.getId()); |
|
131 |
+ List<Attachment> cachedData = AttachmentCache.get(container); |
|
132 |
+ if (cachedData != null) { |
|
133 |
+ return cachedData; |
|
134 |
+ } |
|
135 |
+ |
|
136 |
+ List<Attachment> list = findByContainer(container.getType(), container.getId()); |
|
137 |
+ AttachmentCache.set(container, list); |
|
138 |
+ return list; |
|
124 | 139 |
} |
125 | 140 |
|
126 | 141 |
/** |
... | ... | @@ -289,7 +304,8 @@ |
289 | 304 |
} |
290 | 305 |
|
291 | 306 |
/** |
292 |
- * Deletes this file. |
|
307 |
+ * Deletes this file and remove cache that contains it. |
|
308 |
+ * However, the cache can not be removed if Ebean.delete() is directly used or called by cascading. |
|
293 | 309 |
* |
294 | 310 |
* This method is used when an user delete an attachment or its container. |
295 | 311 |
*/ |
... | ... | @@ -311,6 +327,18 @@ |
311 | 327 |
play.Logger.error("Failed to delete: " + this, e); |
312 | 328 |
} |
313 | 329 |
} |
330 |
+ |
|
331 |
+ AttachmentCache.remove(this); |
|
332 |
+ } |
|
333 |
+ |
|
334 |
+ /** |
|
335 |
+ * Update this file and remove cache that contains it. |
|
336 |
+ * However, the cache can not be removed if Ebean.update() is directly used or called by cascading. |
|
337 |
+ */ |
|
338 |
+ @Override |
|
339 |
+ public void update() { |
|
340 |
+ super.update(); |
|
341 |
+ AttachmentCache.remove(this); |
|
314 | 342 |
} |
315 | 343 |
|
316 | 344 |
|
... | ... | @@ -434,7 +462,7 @@ |
434 | 462 |
attachment.delete(); |
435 | 463 |
deletedFileCount++; |
436 | 464 |
} |
437 |
- if( attachmentList.size() != deletedFileCount) { |
|
465 |
+ if (attachmentList.size() != deletedFileCount) { |
|
438 | 466 |
play.Logger.error( |
439 | 467 |
String.format("Failed to delete user temporary files.\nExpected: %d Actual: %d", |
440 | 468 |
attachmentList.size(), deletedFileCount) |
... | ... | @@ -524,6 +552,8 @@ |
524 | 552 |
this.name = fileName; |
525 | 553 |
} |
526 | 554 |
|
555 |
+ AttachmentCache.remove(this); |
|
556 |
+ |
|
527 | 557 |
// Add the attachment into the Database only if there is no same record. |
528 | 558 |
Attachment sameAttach = Attachment.findBy(this); |
529 | 559 |
if (sameAttach == null) { |
+++ app/utils/AttachmentCache.java
... | ... | @@ -0,0 +1,104 @@ |
1 | +package utils; | |
2 | + | |
3 | +import models.Attachment; | |
4 | +import models.enumeration.ResourceType; | |
5 | +import models.resource.Resource; | |
6 | +import play.cache.Cache; | |
7 | + | |
8 | +import java.util.List; | |
9 | + | |
10 | +/** | |
11 | + * Utility for caching attachments in a container {@link models.resource.Resource}. | |
12 | + * | |
13 | + * The key is made by the name of the type of the Resource and Resource's id. | |
14 | + * i.e) resource.getType().name() + resource.getId() | |
15 | + * | |
16 | + * The value is a collection of attachments. | |
17 | + * | |
18 | + * @author Keeun Baik | |
19 | + */ | |
20 | +public class AttachmentCache { | |
21 | + | |
22 | + /** | |
23 | + * Play's Cache API allows expiration time in seconds. | |
24 | + * | |
25 | + * @see {@link play.cache.Cache#set(String, Object, int)} | |
26 | + */ | |
27 | + private static final int ONE_DAY = 60 * 60 * 24; | |
28 | + | |
29 | + /** | |
30 | + * Find cached attachments with the key is generated by | |
31 | + * combining {@code containerType} and {@code containerId}. | |
32 | + * | |
33 | + * @param containerType | |
34 | + * @param containerId | |
35 | + * @return found cached data or null if there is no cached data. | |
36 | + */ | |
37 | + public static List<Attachment> get(ResourceType containerType, String containerId) { | |
38 | + String cacheKey = containerType.name() + containerId; | |
39 | + Object cachedData = Cache.get(cacheKey); | |
40 | + if (cachedData != null) { | |
41 | + return (List<Attachment>) cachedData; | |
42 | + } else { | |
43 | + return null; | |
44 | + } | |
45 | + } | |
46 | + | |
47 | + /** | |
48 | + * Cache attachments with the key | |
49 | + * | |
50 | + * @param key The key should be generated by combining {@code containerType} and {@code containerId}. | |
51 | + * @param list | |
52 | + */ | |
53 | + public static void set(String key, List<Attachment> list) { | |
54 | + Cache.set(key, list, ONE_DAY); | |
55 | + } | |
56 | + | |
57 | + /** | |
58 | + * Cache attachments with the key is generated by {@code container} | |
59 | + * | |
60 | + * @param container | |
61 | + * @param list | |
62 | + */ | |
63 | + public static void set(Resource container, List<Attachment> list) { | |
64 | + Cache.set(cacheKey(container), list, ONE_DAY); | |
65 | + } | |
66 | + | |
67 | + /** | |
68 | + * Find cached attachments with the key is generated by {@code container} | |
69 | + * | |
70 | + * @param container | |
71 | + * @return | |
72 | + */ | |
73 | + public static List<Attachment> get(Resource container) { | |
74 | + String cacheKey = cacheKey(container); | |
75 | + Object cachedData = Cache.get(cacheKey); | |
76 | + if (cachedData != null) { | |
77 | + return (List<Attachment>) cachedData; | |
78 | + } else { | |
79 | + return null; | |
80 | + } | |
81 | + } | |
82 | + | |
83 | + private static String cacheKey(Resource container) { | |
84 | + return container.getType().name() + container.getId(); | |
85 | + } | |
86 | + | |
87 | + /** | |
88 | + * Remove cached attachments with the key is generated by {@code container} | |
89 | + * | |
90 | + * @param container | |
91 | + */ | |
92 | + public static void remove(Resource container) { | |
93 | + Cache.remove(cacheKey(container)); | |
94 | + } | |
95 | + | |
96 | + /** | |
97 | + * Remove cache that contains the {@code attachment} | |
98 | + * | |
99 | + * @param attachment | |
100 | + */ | |
101 | + public static void remove(Attachment attachment) { | |
102 | + Cache.remove(attachment.containerType.name() + attachment.containerId); | |
103 | + } | |
104 | +} |
--- build.sbt
+++ build.sbt
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 |
javaCore, |
16 | 16 |
javaJdbc, |
17 | 17 |
javaEbean, |
18 |
+ cache, |
|
18 | 19 |
// Add your project dependencies here, |
19 | 20 |
"com.h2database" % "h2" % "1.4.184", |
20 | 21 |
// Core Library |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?