From 60c0892466c8e48faba3e7bbe2b462c47aa032fa Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Sat, 13 Jun 2020 19:22:25 +0200 Subject: Benki: Cache HTML renderings of posts in the database. Change-Id: I3367ceb8769d354f64165d23ec7ed1f2155c4c49 --- .../eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java | 2 +- .../mulkcms2/benki/bookmarks/BookmarkResource.java | 1 + .../mulkcms2/benki/lazychat/LazychatMessage.java | 12 +++---- .../mulkcms2/benki/lazychat/LazychatResource.java | 1 + .../java/eu/mulk/mulkcms2/benki/posts/Post.java | 40 ++++++++++++++++++++-- .../eu/mulk/mulkcms2/benki/posts/PostResource.java | 13 ++++++- src/main/resources/db/changeLog-1.1.xml | 26 ++++++++++++++ src/main/resources/db/changeLog.xml | 1 + 8 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 src/main/resources/db/changeLog-1.1.xml diff --git a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java index 5c1342a..a659049 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/Bookmark.java @@ -38,7 +38,7 @@ public class Bookmark extends Post { @Transient @CheckForNull - public String getDescriptionHtml() { + protected String computeDescriptionHtml() { if (description == null) { return null; } diff --git a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java index 059335c..f81ed04 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/bookmarks/BookmarkResource.java @@ -109,6 +109,7 @@ public class BookmarkResource extends PostResource { bookmark.title = title; bookmark.tags = Set.of(); bookmark.description = description; + bookmark.cachedDescriptionHtml = null; bookmark.owner = user; assignPostTargets(visibility, user, bookmark); diff --git a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java index ffafb96..5cec6aa 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatMessage.java @@ -31,10 +31,7 @@ public class LazychatMessage extends Post { @JsonbTransient @CheckForNull public String getContentHtml() { - if (content == null) { - return null; - } - return new MarkdownConverter().htmlify(content); + return getDescriptionHtml(); } @CheckForNull @@ -52,8 +49,11 @@ public class LazychatMessage extends Post { @CheckForNull @Override @JsonbTransient - public String getDescriptionHtml() { - return getContentHtml(); + protected String computeDescriptionHtml() { + if (content == null) { + return null; + } + return new MarkdownConverter().htmlify(content); } @Override diff --git a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java index cbdbe76..156b638 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/lazychat/LazychatResource.java @@ -82,6 +82,7 @@ public class LazychatResource extends PostResource { } message.content = text; + message.cachedDescriptionHtml = null; message.format = "markdown"; assignPostTargets(visibility, user, message); diff --git a/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java b/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java index bbfafa2..aa15fa2 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/Post.java @@ -47,6 +47,8 @@ public abstract class Post extends PanacheEntityBase { private static final Logger log = Logger.getLogger(Post.class); + private static final int DESCRIPTION_CACHE_VERSION = 1; + @Id @SequenceGenerator( allocationSize = 1, @@ -61,6 +63,14 @@ public abstract class Post extends PanacheEntityBase { @CheckForNull public OffsetDateTime date; + @Column(name = "cached_description_version", nullable = true) + @CheckForNull + public Integer cachedDescriptionVersion; + + @Column(name = "cached_description_html", nullable = true) + @CheckForNull + public String cachedDescriptionHtml; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "owner", referencedColumnName = "id") @CheckForNull @@ -93,7 +103,21 @@ public abstract class Post extends PanacheEntityBase { public abstract String getTitle(); @CheckForNull - public abstract String getDescriptionHtml(); + public final String getDescriptionHtml() { + if (cachedDescriptionHtml != null && + cachedDescriptionVersion != null && + cachedDescriptionVersion >= DESCRIPTION_CACHE_VERSION){ + return cachedDescriptionHtml; + } else { + @CheckForNull var descriptionHtml = computeDescriptionHtml(); + cachedDescriptionHtml = descriptionHtml; + cachedDescriptionVersion = DESCRIPTION_CACHE_VERSION; + return descriptionHtml; + } + } + + @CheckForNull + protected abstract String computeDescriptionHtml(); @CheckForNull public abstract String getUri(); @@ -190,6 +214,10 @@ public abstract class Post extends PanacheEntityBase { this.posts = resultList; } + public void cacheDescriptions() { + days().forEach(Day::cacheDescriptions); + } + public class Day { public final @CheckForNull LocalDate date; public final List posts; @@ -198,6 +226,12 @@ public abstract class Post extends PanacheEntityBase { this.date = date; this.posts = posts; } + + public void cacheDescriptions() { + for (var post : posts) { + post.getDescriptionHtml(); + } + } } public List days() { @@ -211,9 +245,9 @@ public abstract class Post extends PanacheEntityBase { } } - public static List findViewable( + public static PostPage findViewable( PostFilter postFilter, Session session, @CheckForNull User viewer, @CheckForNull User owner) { - return findViewable(postFilter, session, viewer, owner, null, null).posts; + return findViewable(postFilter, session, viewer, owner, null, null); } public static PostPage findViewable( diff --git a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java index 580f8bc..f58140e 100644 --- a/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java +++ b/src/main/java/eu/mulk/mulkcms2/benki/posts/PostResource.java @@ -113,6 +113,7 @@ public abstract class PostResource { @GET @Produces(TEXT_HTML) + @Transactional public TemplateInstance getIndex( @QueryParam("i") @CheckForNull Integer cursor, @QueryParam("n") @CheckForNull Integer maxResults) { @@ -123,6 +124,8 @@ public abstract class PostResource { var session = entityManager.unwrap(Session.class); var q = Post.findViewable(postFilter, session, reader, null, cursor, maxResults); + q.cacheDescriptions(); + var feedUri = uri.getPath() + "/feed"; if (reader != null) { var pageKey = ensurePageKey(reader, feedUri); @@ -145,6 +148,7 @@ public abstract class PostResource { @GET @Path("~{ownerName}") @Produces(TEXT_HTML) + @Transactional public TemplateInstance getUserIndex( @PathParam("ownerName") String ownerName, @QueryParam("i") @CheckForNull Integer cursor, @@ -157,6 +161,8 @@ public abstract class PostResource { var session = entityManager.unwrap(Session.class); var q = Post.findViewable(postFilter, session, reader, owner, cursor, maxResults); + q.cacheDescriptions(); + var feedUri = uri.getPath() + "/feed"; if (reader != null) { var pageKey = ensurePageKey(reader, feedUri); @@ -219,6 +225,7 @@ public abstract class PostResource { @GET @Path("feed") @Produces(APPLICATION_ATOM_XML) + @Transactional public String getFeed(@QueryParam("page-key") @CheckForNull String pageKeyBase36) throws FeedException { @CheckForNull var pageKey = pageKeyBase36 == null ? null : new BigInteger(pageKeyBase36, 36); @@ -228,6 +235,7 @@ public abstract class PostResource { @GET @Path("~{ownerName}/feed") @Produces(APPLICATION_ATOM_XML) + @Transactional public String getUserFeed( @QueryParam("page-key") @CheckForNull String pageKeyBase36, @PathParam("ownerName") String ownerName) @@ -257,7 +265,10 @@ public abstract class PostResource { private String makeFeed( @CheckForNull User reader, @Nullable User owner, @Nullable String ownerName) throws FeedException { - var posts = Post.findViewable(postFilter, entityManager.unwrap(Session.class), reader, owner); + var q = Post.findViewable(postFilter, entityManager.unwrap(Session.class), reader, owner); + q.cacheDescriptions(); + var posts = q.posts; + var feed = new Feed("atom_1.0"); var feedSubId = owner == null ? "" : String.format("/%d", owner.id); diff --git a/src/main/resources/db/changeLog-1.1.xml b/src/main/resources/db/changeLog-1.1.xml new file mode 100644 index 0000000..b32f983 --- /dev/null +++ b/src/main/resources/db/changeLog-1.1.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changeLog.xml b/src/main/resources/db/changeLog.xml index bae8dda..7d346aa 100644 --- a/src/main/resources/db/changeLog.xml +++ b/src/main/resources/db/changeLog.xml @@ -7,5 +7,6 @@ http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.9.xsd"> + -- cgit v1.2.3