Benki: Cache HTML renderings of posts in the database.
Change-Id: I3367ceb8769d354f64165d23ec7ed1f2155c4c49
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 @@
@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 @@
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 @@
@JsonbTransient
@CheckForNull
public String getContentHtml() {
- if (content == null) {
- return null;
- }
- return new MarkdownConverter().htmlify(content);
+ return getDescriptionHtml();
}
@CheckForNull
@@ -52,8 +49,11 @@
@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 @@
}
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 @@
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 @@
@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 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 @@
this.posts = resultList;
}
+ public void cacheDescriptions() {
+ days().forEach(Day::cacheDescriptions);
+ }
+
public class Day {
public final @CheckForNull LocalDate date;
public final List<T> posts;
@@ -198,6 +226,12 @@
this.date = date;
this.posts = posts;
}
+
+ public void cacheDescriptions() {
+ for (var post : posts) {
+ post.getDescriptionHtml();
+ }
+ }
}
public List<Day> days() {
@@ -211,9 +245,9 @@
}
}
- public static List<Post> findViewable(
+ public static PostPage<Post> 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<Post> 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 @@
@GET
@Produces(TEXT_HTML)
+ @Transactional
public TemplateInstance getIndex(
@QueryParam("i") @CheckForNull Integer cursor,
@QueryParam("n") @CheckForNull Integer maxResults) {
@@ -123,6 +124,8 @@
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 @@
@GET
@Path("~{ownerName}")
@Produces(TEXT_HTML)
+ @Transactional
public TemplateInstance getUserIndex(
@PathParam("ownerName") String ownerName,
@QueryParam("i") @CheckForNull Integer cursor,
@@ -157,6 +161,8 @@
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 @@
@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 @@
@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 @@
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 @@
+<?xml version="1.1" encoding="UTF-8" standalone="no"?>
+<databaseChangeLog
+ xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.liquibase.org/xml/ns/dbchangelog
+ http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.9.xsd">
+
+ <changeSet author="mulk" id="1.1-1">
+ <addColumn tableName="lazychat_messages" schemaName="benki">
+ <column name="cached_description_html" type="varchar"/>
+ <column name="cached_description_version" type="integer"/>
+ </addColumn>
+
+ <addColumn tableName="bookmarks" schemaName="benki">
+ <column name="cached_description_html" type="varchar"/>
+ <column name="cached_description_version" type="integer"/>
+ </addColumn>
+
+ <addColumn tableName="posts" schemaName="benki">
+ <column name="cached_description_html" type="varchar"/>
+ <column name="cached_description_version" type="integer"/>
+ </addColumn>
+ </changeSet>
+
+</databaseChangeLog>
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">
<include file="db/changeLog-1.0.xml"/>
+ <include file="db/changeLog-1.1.xml"/>
</databaseChangeLog>