2424import io .micrometer .core .annotation .Timed ;
2525import jakarta .servlet .http .HttpSession ;
2626import java .security .Principal ;
27- import java .util .Collections ;
28- import java .util .List ;
27+ import java .util .*;
28+ import java .util .concurrent .ConcurrentHashMap ;
29+ import lombok .AllArgsConstructor ;
30+ import lombok .Getter ;
2931import lombok .extern .log4j .Log4j2 ;
32+ import org .comixedproject .model .comicbooks .ComicState ;
3033import org .comixedproject .model .comicbooks .ComicTagType ;
3134import org .comixedproject .model .library .DisplayableComic ;
3235import org .comixedproject .model .net .library .*;
4043import org .comixedproject .service .lists .ReadingListService ;
4144import org .comixedproject .service .user .ComiXedUserException ;
4245import org .comixedproject .service .user .UserService ;
46+ import org .comixedproject .state .comicbooks .ComicEvent ;
47+ import org .comixedproject .state .comicbooks .ComicStateChangeListener ;
48+ import org .comixedproject .state .comicbooks .ComicStateHandler ;
4349import org .comixedproject .views .View ;
50+ import org .springframework .beans .factory .InitializingBean ;
4451import org .springframework .beans .factory .annotation .Autowired ;
4552import org .springframework .http .MediaType ;
53+ import org .springframework .messaging .Message ;
4654import org .springframework .security .access .prepost .PreAuthorize ;
55+ import org .springframework .statemachine .state .State ;
4756import org .springframework .web .bind .annotation .PathVariable ;
4857import org .springframework .web .bind .annotation .PostMapping ;
4958import org .springframework .web .bind .annotation .RequestBody ;
5766 */
5867@ RestController
5968@ Log4j2
60- public class DisplayableComicController {
69+ public class DisplayableComicController implements InitializingBean , ComicStateChangeListener {
6170 @ Autowired private DisplayableComicService displayableComicService ;
6271 @ Autowired private ComicBookService comicBookService ;
6372 @ Autowired private ComicSelectionService comicSelectionService ;
6473 @ Autowired private UserService userService ;
6574 @ Autowired private ReadingListService readingListService ;
75+ @ Autowired private ComicStateHandler comicStateHandler ;
76+
77+ Map <LoadComicsByFilterRequest , LoadComicsResponse > filterCache = new ConcurrentHashMap <>();
78+ Map <TagTypeAndValue , LoadComicsResponse > tagAndValueCache = new ConcurrentHashMap <>();
79+
80+ @ Override
81+ public void afterPropertiesSet () {
82+ log .trace ("Registering for comic state change updates" );
83+ this .comicStateHandler .addListener (this );
84+ }
85+
86+ @ Override
87+ public void onComicStateChange (
88+ final State <ComicState , ComicEvent > state , final Message <ComicEvent > message ) {
89+ log .debug ("Cleaning comic caches" );
90+ this .filterCache .clear ();
91+ this .tagAndValueCache .clear ();
92+ }
6693
6794 /**
6895 * Loads one page's worth of displayable comics.
@@ -80,6 +107,10 @@ public class DisplayableComicController {
80107 public LoadComicsResponse loadComicsByFilter (
81108 @ RequestBody () final LoadComicsByFilterRequest request ) {
82109 log .info ("Loading comics: {}" , request );
110+ if (this .filterCache .containsKey (request )) {
111+ log .info ("Cache hit for request" );
112+ return this .filterCache .get (request );
113+ }
83114 final List <DisplayableComic > comics =
84115 this .displayableComicService .loadComicsByFilter (
85116 request .getPageSize (),
@@ -133,7 +164,10 @@ public LoadComicsResponse loadComicsByFilter(
133164 request .getVolume (),
134165 request .getPageCount ());
135166 final long totalCount = this .comicBookService .getComicBookCount ();
136- return new LoadComicsResponse (comics , coverYears , coverMonths , totalCount , filterCount );
167+ final LoadComicsResponse response =
168+ new LoadComicsResponse (comics , coverYears , coverMonths , totalCount , filterCount );
169+ this .filterCache .put (request , response );
170+ return response ;
137171 }
138172
139173 /**
@@ -192,17 +226,26 @@ public LoadComicsResponse loadComicsByTagTypeAndValue(
192226 final int pageIndex = request .getPageIndex ();
193227 final String sortBy = request .getSortBy ();
194228 final String sortDirection = request .getSortDirection ();
229+ final TagTypeAndValue key =
230+ new TagTypeAndValue (tagType , tagValue , pageSize , pageIndex , sortBy , sortDirection );
231+ if (this .tagAndValueCache .containsKey (key )) {
232+ log .info ("Cache hit for tag: {}={}" , tagType , tagValue );
233+ return this .tagAndValueCache .get (key );
234+ }
195235 final List <DisplayableComic > comicDetails =
196236 this .displayableComicService .loadComicsByTagTypeAndValue (
197237 pageSize , pageIndex , tagType , tagValue , sortBy , sortDirection );
198238 final long filteredComics =
199239 this .displayableComicService .getComicCountForTagTypeAndValue (tagType , tagValue );
200- return new LoadComicsResponse (
201- comicDetails ,
202- this .displayableComicService .getCoverYearsForTagTypeAndValue (tagType , tagValue ),
203- this .displayableComicService .getCoverMonthsForTagTypeAndValue (tagType , tagValue ),
204- filteredComics ,
205- filteredComics );
240+ final LoadComicsResponse result =
241+ new LoadComicsResponse (
242+ comicDetails ,
243+ this .displayableComicService .getCoverYearsForTagTypeAndValue (tagType , tagValue ),
244+ this .displayableComicService .getCoverMonthsForTagTypeAndValue (tagType , tagValue ),
245+ filteredComics ,
246+ filteredComics );
247+ this .tagAndValueCache .put (key , result );
248+ return result ;
206249 }
207250
208251 /**
@@ -307,4 +350,32 @@ public LoadComicsResponse loadComicsForList(
307350 return new LoadComicsResponse (
308351 comics , Collections .emptyList (), Collections .emptyList (), filterCount , filterCount );
309352 }
353+
354+ @ AllArgsConstructor
355+ static class TagTypeAndValue {
356+ @ Getter private ComicTagType tagType ;
357+ @ Getter private String value ;
358+ @ Getter private int pageSize ;
359+ @ Getter private int pageIndex ;
360+ @ Getter private String sortBy ;
361+ @ Getter private String sortDirection ;
362+
363+ @ Override
364+ public boolean equals (final Object o ) {
365+ if (o == null || getClass () != o .getClass ()) return false ;
366+ final TagTypeAndValue that = (TagTypeAndValue ) o ;
367+ return getPageSize () == that .getPageSize ()
368+ && getPageIndex () == that .getPageIndex ()
369+ && getTagType () == that .getTagType ()
370+ && Objects .equals (getValue (), that .getValue ())
371+ && Objects .equals (getSortBy (), that .getSortBy ())
372+ && Objects .equals (getSortDirection (), that .getSortDirection ());
373+ }
374+
375+ @ Override
376+ public int hashCode () {
377+ return Objects .hash (
378+ getTagType (), getValue (), getPageSize (), getPageIndex (), getSortBy (), getSortDirection ());
379+ }
380+ }
310381}
0 commit comments