From b54673cc1214a0a4dd48e4e4fcdd3904046615a1 Mon Sep 17 00:00:00 2001 From: ZJamss Date: Sat, 30 Mar 2024 19:57:27 +0800 Subject: [PATCH 1/9] refactor by reconciler Signed-off-by: ZJamss --- .../reconciler/PostCounterReconciler.java | 7 +++++++ .../halo/app/event/post/PostChangeEvent.java | 20 +++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java create mode 100644 application/src/main/java/run/halo/app/event/post/PostChangeEvent.java diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java new file mode 100644 index 0000000000..bffb9a9427 --- /dev/null +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java @@ -0,0 +1,7 @@ +package run.halo.app.core.extension.reconciler;/** + * @className: PostCounterReconciler + * @description: TODO + * @author: ZJAMSS + * @date: 2024/3/30 + **/public class PostCounterReconciler { +} diff --git a/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java b/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java new file mode 100644 index 0000000000..0302e74545 --- /dev/null +++ b/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java @@ -0,0 +1,20 @@ +package run.halo.app.event.post; + +import org.springframework.context.ApplicationEvent; + +/** + * @author ZJamss + */ +public class PostChangeEvent extends ApplicationEvent implements PostEvent{ + private final String name; + + public PostChangeEvent(Object source, String post) { + super(source); + this.name = post; + } + + @Override + public String getName() { + return this.name; + } +} From f6a7e844157d23b82e45beb8a4492c09afa64d0c Mon Sep 17 00:00:00 2001 From: ZJamss Date: Sat, 30 Mar 2024 20:02:38 +0800 Subject: [PATCH 2/9] refactor by reconciler Signed-off-by: ZJamss --- .../halo/app/core/extension/content/Post.java | 3 + .../reconciler/PostCounterReconciler.java | 114 +++++++++++++++++- .../extension/reconciler/PostReconciler.java | 2 + .../run/halo/app/infra/SchemeInitializer.java | 13 ++ .../modules/contents/posts/PostList.vue | 8 ++ ui/src/locales/en.yaml | 2 + ui/src/locales/es.yaml | 2 + ui/src/locales/zh-CN.yaml | 2 + ui/src/locales/zh-TW.yaml | 2 + 9 files changed, 142 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/run/halo/app/core/extension/content/Post.java b/api/src/main/java/run/halo/app/core/extension/content/Post.java index 6d51ba0edb..b3a28f2924 100644 --- a/api/src/main/java/run/halo/app/core/extension/content/Post.java +++ b/api/src/main/java/run/halo/app/core/extension/content/Post.java @@ -43,6 +43,9 @@ public class Post extends AbstractExtension { "content.halo.run/last-released-snapshot"; public static final String LAST_ASSOCIATED_TAGS_ANNO = "content.halo.run/last-associated-tags"; + public static final String COUNTER_VISIT_ANNO = "counter.visit"; + public static final String COUNTER_COMMENT_ANNO = "counter.comment"; + public static final String DELETED_LABEL = "content.halo.run/deleted"; public static final String PUBLISHED_LABEL = "content.halo.run/published"; public static final String OWNER_LABEL = "content.halo.run/owner"; diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java index bffb9a9427..2b18ae8967 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java @@ -1,7 +1,109 @@ -package run.halo.app.core.extension.reconciler;/** - * @className: PostCounterReconciler - * @description: TODO - * @author: ZJAMSS - * @date: 2024/3/30 - **/public class PostCounterReconciler { +package run.halo.app.core.extension.reconciler; + +import org.springframework.boot.context.event.ApplicationStartedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.data.domain.Sort; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import run.halo.app.core.extension.Counter; +import run.halo.app.core.extension.content.Post; +import run.halo.app.event.post.PostChangeEvent; +import run.halo.app.extension.ExtensionClient; +import run.halo.app.extension.GroupVersionKind; +import run.halo.app.extension.ListOptions; +import run.halo.app.extension.controller.Controller; +import run.halo.app.extension.controller.ControllerBuilder; +import run.halo.app.extension.controller.Reconciler; +import run.halo.app.extension.index.Indexer; +import run.halo.app.extension.index.IndexerFactoryImpl; +import run.halo.app.metrics.MeterUtils; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; + +@Component +public class PostCounterReconciler implements Reconciler { + + private final ExtensionClient client; + + private final IndexerFactoryImpl indexerFactory; + + private final Set set; + + public PostCounterReconciler(ExtensionClient client, IndexerFactoryImpl indexerFactory) { + this.client = client; + this.indexerFactory = indexerFactory; + this.set = new CopyOnWriteArraySet<>(); + } + + @Override + public Result reconcile(Request request) { + String name = request.name(); + client.fetch(Counter.class, name).ifPresent(counter -> { + set.add(getPostName(name)); + }); + return Result.doNotRetry(); + } + + + @Scheduled(cron = "0/3 * * * * ?") + public void handleSetRequest() { + Iterator iterator = set.iterator(); + while (iterator.hasNext()) { + String name = iterator.next(); + updateCounter(name); + set.remove(name); + } + } + + private void updateCounter(String postName) { + + client.fetch(Post.class, postName) + .ifPresent(post -> { + client.fetch(Counter.class, + MeterUtils.nameOf(Post.class, post.getMetadata().getName())) + .ifPresent(queryCounter -> { + post.getMetadata().getAnnotations() + .put(Post.COUNTER_VISIT_ANNO, queryCounter.getVisit().toString()); + post.getMetadata().getAnnotations() + .put(Post.COUNTER_COMMENT_ANNO, + queryCounter.getTotalComment().toString()); + updateIndexByPost(post); + }); + }); + } + + public void updateIndexByPost(Post post) { + GroupVersionKind gvk = GroupVersionKind.fromExtension(Post.class); + Indexer indexer = indexerFactory.getIndexer(gvk); + indexer.updateRecord(post); + } + + @Override + public Controller setupWith(ControllerBuilder builder) { + return builder.extension(new Counter()).syncAllOnStart(false).build(); + } + + @EventListener(ApplicationStartedEvent.class) + public void preBuildCounterIndexes() { + client.listAll(Counter.class, new ListOptions(), Sort.unsorted()).forEach(counter -> { + client.fetch(Post.class, getPostName(counter.getMetadata().getName())) + .ifPresent(post -> { + post.getMetadata().getAnnotations() + .put(Post.COUNTER_VISIT_ANNO, counter.getVisit().toString()); + post.getMetadata().getAnnotations() + .put(Post.COUNTER_COMMENT_ANNO, counter.getTotalComment().toString()); + updateIndexByPost(post); + }); + }); + } + + @EventListener(PostChangeEvent.class) + public void onPostChanged(PostChangeEvent event) { + set.add(event.getName()); + } + + public String getPostName(String counterName) { + return counterName.split("/")[1]; + } } diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostReconciler.java index 90b01017a4..8a87e0c2a0 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PostReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostReconciler.java @@ -33,6 +33,7 @@ import run.halo.app.core.extension.content.Post.VisibleEnum; import run.halo.app.core.extension.content.Snapshot; import run.halo.app.core.extension.notification.Subscription; +import run.halo.app.event.post.PostChangeEvent; import run.halo.app.event.post.PostDeletedEvent; import run.halo.app.event.post.PostPublishedEvent; import run.halo.app.event.post.PostUnpublishedEvent; @@ -83,6 +84,7 @@ public class PostReconciler implements Reconciler { @Override public Result reconcile(Request request) { var events = new HashSet(); + events.add(new PostChangeEvent(this, request.name())); client.fetch(Post.class, request.name()) .ifPresent(post -> { if (ExtensionOperator.isDeleted(post)) { diff --git a/application/src/main/java/run/halo/app/infra/SchemeInitializer.java b/application/src/main/java/run/halo/app/infra/SchemeInitializer.java index e2d1c692a9..c27c421db1 100644 --- a/application/src/main/java/run/halo/app/infra/SchemeInitializer.java +++ b/application/src/main/java/run/halo/app/infra/SchemeInitializer.java @@ -182,6 +182,19 @@ public void onApplicationEvent(@NonNull ApplicationContextInitializedEvent event // do not care about the false case so return null to avoid indexing return null; }))); + + indexSpecs.add(new IndexSpec() + .setName(Post.COUNTER_VISIT_ANNO) + .setIndexFunc( + simpleAttribute(Post.class, + post -> post.getMetadata().getAnnotations().get(Post.COUNTER_VISIT_ANNO)))); + + indexSpecs.add(new IndexSpec() + .setName(Post.COUNTER_COMMENT_ANNO) + .setIndexFunc( + simpleAttribute(Post.class, + post -> post.getMetadata().getAnnotations() + .get(Post.COUNTER_COMMENT_ANNO)))); }); schemeManager.register(Category.class, indexSpecs -> { indexSpecs.add(new IndexSpec() diff --git a/ui/console-src/modules/contents/posts/PostList.vue b/ui/console-src/modules/contents/posts/PostList.vue index 6a51793ec6..c3d403c6b1 100644 --- a/ui/console-src/modules/contents/posts/PostList.vue +++ b/ui/console-src/modules/contents/posts/PostList.vue @@ -420,6 +420,14 @@ watch(selectedPostNames, (newValue) => { label: t('core.post.filters.sort.items.create_time_asc'), value: 'metadata.creationTimestamp,asc', }, + { + label: t('core.post.filters.sort.items.visit_desc'), + value: 'counter.visit,desc', + }, + { + label: t('core.post.filters.sort.items.comment_desc'), + value: 'counter.comment,desc', + }, ]" />
diff --git a/ui/src/locales/en.yaml b/ui/src/locales/en.yaml index f55a611fa1..7377bdd7cd 100644 --- a/ui/src/locales/en.yaml +++ b/ui/src/locales/en.yaml @@ -217,6 +217,8 @@ core: publish_time_asc: Earliest Published create_time_desc: Latest Created create_time_asc: Earliest Created + visit_desc: Most Visits + comment_desc: Most Comments list: fields: categories: "Categories:" diff --git a/ui/src/locales/es.yaml b/ui/src/locales/es.yaml index 28588bd148..ede3640151 100644 --- a/ui/src/locales/es.yaml +++ b/ui/src/locales/es.yaml @@ -179,6 +179,8 @@ core: publish_time_asc: Publicado más antiguo create_time_desc: Creado más reciente create_time_asc: Creado más antiguo + visit_desc: Máximo de visitas + comment_desc: Número máximo de comentarios list: fields: categories: "Categorías:" diff --git a/ui/src/locales/zh-CN.yaml b/ui/src/locales/zh-CN.yaml index 9844cb891b..d11a25679c 100644 --- a/ui/src/locales/zh-CN.yaml +++ b/ui/src/locales/zh-CN.yaml @@ -209,6 +209,8 @@ core: publish_time_asc: 较早发布 create_time_desc: 较近创建 create_time_asc: 较早创建 + visit_desc: 最多访问量 + comment_desc: 最多评论量 list: fields: categories: 分类: diff --git a/ui/src/locales/zh-TW.yaml b/ui/src/locales/zh-TW.yaml index 31517402cb..4b4dff93b5 100644 --- a/ui/src/locales/zh-TW.yaml +++ b/ui/src/locales/zh-TW.yaml @@ -209,6 +209,8 @@ core: publish_time_asc: 較早發布 create_time_desc: 較近創建 create_time_asc: 較早創建 + visit_desc: 最多訪問量 + comment_desc: 最多評論量 list: fields: categories: 分類: From 9d7b267e525c879b8ffe4283d5f1d5156c09176d Mon Sep 17 00:00:00 2001 From: ZJamss Date: Mon, 1 Apr 2024 18:12:45 +0800 Subject: [PATCH 3/9] Reformatted code to follow Checkstyle Signed-off-by: ZJamss --- .../extension/reconciler/PostCounterReconciler.java | 11 +++++++---- .../java/run/halo/app/event/post/PostChangeEvent.java | 5 +---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java index 2b18ae8967..21d57916db 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java @@ -1,5 +1,8 @@ package run.halo.app.core.extension.reconciler; +import java.util.Iterator; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.event.EventListener; import org.springframework.data.domain.Sort; @@ -17,9 +20,7 @@ import run.halo.app.extension.index.Indexer; import run.halo.app.extension.index.IndexerFactoryImpl; import run.halo.app.metrics.MeterUtils; -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; + @Component public class PostCounterReconciler implements Reconciler { @@ -81,7 +82,9 @@ public void updateIndexByPost(Post post) { @Override public Controller setupWith(ControllerBuilder builder) { - return builder.extension(new Counter()).syncAllOnStart(false).build(); + return builder + .extension(new Counter()) + .syncAllOnStart(false).build(); } @EventListener(ApplicationStartedEvent.class) diff --git a/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java b/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java index 0302e74545..8cc95350bd 100644 --- a/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java +++ b/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java @@ -2,10 +2,7 @@ import org.springframework.context.ApplicationEvent; -/** - * @author ZJamss - */ -public class PostChangeEvent extends ApplicationEvent implements PostEvent{ +public class PostChangeEvent extends ApplicationEvent implements PostEvent { private final String name; public PostChangeEvent(Object source, String post) { From 31f60b4808fa24a0b2c6eaa997e6095872d55f63 Mon Sep 17 00:00:00 2001 From: ZJamss Date: Mon, 1 Apr 2024 21:05:08 +0800 Subject: [PATCH 4/9] Refactored the code based on the suggestions from the conversations Signed-off-by: ZJamss --- .../halo/app/core/extension/content/Post.java | 3 +- .../controller/ControllerBuilder.java | 10 +- .../reconciler/PostCounterReconciler.java | 100 +++++++----------- .../run/halo/app/infra/SchemeInitializer.java | 27 ++++- 4 files changed, 73 insertions(+), 67 deletions(-) diff --git a/api/src/main/java/run/halo/app/core/extension/content/Post.java b/api/src/main/java/run/halo/app/core/extension/content/Post.java index b3a28f2924..792edc218f 100644 --- a/api/src/main/java/run/halo/app/core/extension/content/Post.java +++ b/api/src/main/java/run/halo/app/core/extension/content/Post.java @@ -43,8 +43,7 @@ public class Post extends AbstractExtension { "content.halo.run/last-released-snapshot"; public static final String LAST_ASSOCIATED_TAGS_ANNO = "content.halo.run/last-associated-tags"; - public static final String COUNTER_VISIT_ANNO = "counter.visit"; - public static final String COUNTER_COMMENT_ANNO = "counter.comment"; + public static final String COUNTER_ANNO = "content.halo.run/counter"; public static final String DELETED_LABEL = "content.halo.run/deleted"; public static final String PUBLISHED_LABEL = "content.halo.run/published"; diff --git a/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java b/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java index 2bfcd9c4c4..417a36a757 100644 --- a/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java +++ b/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java @@ -35,6 +35,7 @@ public class ControllerBuilder { private boolean syncAllOnStart = true; private int workerCount = 1; + private RequestQueue queue; public ControllerBuilder(Reconciler reconciler, ExtensionClient client) { Assert.notNull(reconciler, "Reconciler must not be null"); @@ -89,6 +90,11 @@ public ControllerBuilder workerCount(int workerCount) { return this; } + public ControllerBuilder queue(RequestQueue queue) { + this.queue = queue; + return this; + } + public Controller build() { if (nowSupplier == null) { nowSupplier = Instant::now; @@ -104,7 +110,9 @@ public Controller build() { Assert.notNull(extension, "Extension must not be null"); Assert.notNull(reconciler, "Reconciler must not be null"); - var queue = new DefaultQueue(nowSupplier, minDelay); + if (queue == null) { + queue = new DefaultQueue<>(nowSupplier, minDelay); + } var extensionMatchers = WatcherExtensionMatchers.builder(client, extension.groupVersionKind()) .onAddMatcher(onAddMatcher) diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java index 21d57916db..dd73f2dff3 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java @@ -1,24 +1,21 @@ package run.halo.app.core.extension.reconciler; -import java.util.Iterator; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArraySet; -import org.springframework.boot.context.event.ApplicationStartedEvent; +import java.time.Instant; import org.springframework.context.event.EventListener; -import org.springframework.data.domain.Sort; -import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import run.halo.app.core.extension.Counter; import run.halo.app.core.extension.content.Post; import run.halo.app.event.post.PostChangeEvent; import run.halo.app.extension.ExtensionClient; import run.halo.app.extension.GroupVersionKind; -import run.halo.app.extension.ListOptions; import run.halo.app.extension.controller.Controller; import run.halo.app.extension.controller.ControllerBuilder; +import run.halo.app.extension.controller.DefaultQueue; import run.halo.app.extension.controller.Reconciler; +import run.halo.app.extension.controller.RequestQueue; import run.halo.app.extension.index.Indexer; import run.halo.app.extension.index.IndexerFactoryImpl; +import run.halo.app.infra.utils.JsonUtils; import run.halo.app.metrics.MeterUtils; @@ -29,84 +26,69 @@ public class PostCounterReconciler implements Reconciler { private final IndexerFactoryImpl indexerFactory; - private final Set set; + private final RequestQueue queue; + public PostCounterReconciler(ExtensionClient client, IndexerFactoryImpl indexerFactory) { this.client = client; this.indexerFactory = indexerFactory; - this.set = new CopyOnWriteArraySet<>(); + this.queue = new DefaultQueue<>(Instant::now); } @Override public Result reconcile(Request request) { String name = request.name(); - client.fetch(Counter.class, name).ifPresent(counter -> { - set.add(getPostName(name)); - }); - return Result.doNotRetry(); - } - - - @Scheduled(cron = "0/3 * * * * ?") - public void handleSetRequest() { - Iterator iterator = set.iterator(); - while (iterator.hasNext()) { - String name = iterator.next(); - updateCounter(name); - set.remove(name); + if (isPostCounter(name)) { + client.fetch(Counter.class, getCounterName(name)).ifPresent(counter -> { + updateIndexByPost(counter, getPostName(name)); + }); } + return Result.doNotRetry(); } - private void updateCounter(String postName) { - + private void updateIndexByPost(Counter counter, String postName) { client.fetch(Post.class, postName) .ifPresent(post -> { - client.fetch(Counter.class, - MeterUtils.nameOf(Post.class, post.getMetadata().getName())) - .ifPresent(queryCounter -> { - post.getMetadata().getAnnotations() - .put(Post.COUNTER_VISIT_ANNO, queryCounter.getVisit().toString()); - post.getMetadata().getAnnotations() - .put(Post.COUNTER_COMMENT_ANNO, - queryCounter.getTotalComment().toString()); - updateIndexByPost(post); - }); + post.getMetadata().getAnnotations() + .put(Post.COUNTER_ANNO, JsonUtils.objectToJson(counter)); + GroupVersionKind gvk = GroupVersionKind.fromExtension(Post.class); + Indexer indexer = indexerFactory.getIndexer(gvk); + indexer.updateRecord(post); }); } - public void updateIndexByPost(Post post) { - GroupVersionKind gvk = GroupVersionKind.fromExtension(Post.class); - Indexer indexer = indexerFactory.getIndexer(gvk); - indexer.updateRecord(post); - } - @Override public Controller setupWith(ControllerBuilder builder) { return builder .extension(new Counter()) - .syncAllOnStart(false).build(); - } - - @EventListener(ApplicationStartedEvent.class) - public void preBuildCounterIndexes() { - client.listAll(Counter.class, new ListOptions(), Sort.unsorted()).forEach(counter -> { - client.fetch(Post.class, getPostName(counter.getMetadata().getName())) - .ifPresent(post -> { - post.getMetadata().getAnnotations() - .put(Post.COUNTER_VISIT_ANNO, counter.getVisit().toString()); - post.getMetadata().getAnnotations() - .put(Post.COUNTER_COMMENT_ANNO, counter.getTotalComment().toString()); - updateIndexByPost(post); - }); - }); + .syncAllOnStart(true) + .queue(queue) + .build(); } @EventListener(PostChangeEvent.class) public void onPostChanged(PostChangeEvent event) { - set.add(event.getName()); + queue.addImmediately(new Request(event.getName())); + } + + String getPostName(String name) { + if (name.contains("/")) { + return name.split("/")[1]; + } + return name; } - public String getPostName(String counterName) { - return counterName.split("/")[1]; + String getCounterName(String name) { + if (name.contains("/")) { + return name; + } + return MeterUtils.nameOf(Post.class, name); + } + + boolean isPostCounter(String counterName) { + if (counterName.contains("/")) { + return MeterUtils.nameOf(Post.class, getPostName(counterName)).equals(counterName); + } + return true; } } diff --git a/application/src/main/java/run/halo/app/infra/SchemeInitializer.java b/application/src/main/java/run/halo/app/infra/SchemeInitializer.java index c27c421db1..ade5e9eac0 100644 --- a/application/src/main/java/run/halo/app/infra/SchemeInitializer.java +++ b/application/src/main/java/run/halo/app/infra/SchemeInitializer.java @@ -184,17 +184,34 @@ public void onApplicationEvent(@NonNull ApplicationContextInitializedEvent event }))); indexSpecs.add(new IndexSpec() - .setName(Post.COUNTER_VISIT_ANNO) + .setName("counter.visit") .setIndexFunc( simpleAttribute(Post.class, - post -> post.getMetadata().getAnnotations().get(Post.COUNTER_VISIT_ANNO)))); + post -> { + String counterJson = + post.getMetadata().getAnnotations().get(Post.COUNTER_ANNO); + if (counterJson != null) { + return JsonUtils.jsonToObject(counterJson, Counter.class) + .getVisit().toString(); + } + return "0"; + } + ))); indexSpecs.add(new IndexSpec() - .setName(Post.COUNTER_COMMENT_ANNO) + .setName("counter.comment") .setIndexFunc( simpleAttribute(Post.class, - post -> post.getMetadata().getAnnotations() - .get(Post.COUNTER_COMMENT_ANNO)))); + post -> { + String counterJson = + post.getMetadata().getAnnotations().get(Post.COUNTER_ANNO); + if (counterJson != null) { + return JsonUtils.jsonToObject(counterJson, Counter.class) + .getTotalComment().toString(); + } + return "0"; + } + ))); }); schemeManager.register(Category.class, indexSpecs -> { indexSpecs.add(new IndexSpec() From d9a1927f998a279987fb2bc39701444a39753f78 Mon Sep 17 00:00:00 2001 From: ZJamss Date: Mon, 1 Apr 2024 22:08:19 +0800 Subject: [PATCH 5/9] Refactored the reconcilers about counter architecture Signed-off-by: ZJamss --- .../reconciler/PostCounterReconciler.java | 27 ++--- .../run/halo/app/event/post/CounterEvent.java | 18 +++ .../app/event/post/CounterUpdatedEvent.java | 9 ++ .../metrics/PostCounterEventReconciler.java | 103 ++++++++++++++++++ 4 files changed, 137 insertions(+), 20 deletions(-) create mode 100644 application/src/main/java/run/halo/app/event/post/CounterEvent.java create mode 100644 application/src/main/java/run/halo/app/event/post/CounterUpdatedEvent.java create mode 100644 application/src/main/java/run/halo/app/metrics/PostCounterEventReconciler.java diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java index dd73f2dff3..60cf3c7b33 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java @@ -1,21 +1,19 @@ package run.halo.app.core.extension.reconciler; import java.time.Instant; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import run.halo.app.core.extension.Counter; import run.halo.app.core.extension.content.Post; +import run.halo.app.event.post.CounterUpdatedEvent; import run.halo.app.event.post.PostChangeEvent; import run.halo.app.extension.ExtensionClient; -import run.halo.app.extension.GroupVersionKind; import run.halo.app.extension.controller.Controller; import run.halo.app.extension.controller.ControllerBuilder; import run.halo.app.extension.controller.DefaultQueue; import run.halo.app.extension.controller.Reconciler; import run.halo.app.extension.controller.RequestQueue; -import run.halo.app.extension.index.Indexer; -import run.halo.app.extension.index.IndexerFactoryImpl; -import run.halo.app.infra.utils.JsonUtils; import run.halo.app.metrics.MeterUtils; @@ -23,15 +21,14 @@ public class PostCounterReconciler implements Reconciler { private final ExtensionClient client; - - private final IndexerFactoryImpl indexerFactory; - private final RequestQueue queue; + private final ApplicationEventPublisher eventPublisher; - public PostCounterReconciler(ExtensionClient client, IndexerFactoryImpl indexerFactory) { + public PostCounterReconciler(ExtensionClient client, + ApplicationEventPublisher eventPublisher) { this.client = client; - this.indexerFactory = indexerFactory; + this.eventPublisher = eventPublisher; this.queue = new DefaultQueue<>(Instant::now); } @@ -40,22 +37,12 @@ public Result reconcile(Request request) { String name = request.name(); if (isPostCounter(name)) { client.fetch(Counter.class, getCounterName(name)).ifPresent(counter -> { - updateIndexByPost(counter, getPostName(name)); + eventPublisher.publishEvent(new CounterUpdatedEvent(this, counter)); }); } return Result.doNotRetry(); } - private void updateIndexByPost(Counter counter, String postName) { - client.fetch(Post.class, postName) - .ifPresent(post -> { - post.getMetadata().getAnnotations() - .put(Post.COUNTER_ANNO, JsonUtils.objectToJson(counter)); - GroupVersionKind gvk = GroupVersionKind.fromExtension(Post.class); - Indexer indexer = indexerFactory.getIndexer(gvk); - indexer.updateRecord(post); - }); - } @Override public Controller setupWith(ControllerBuilder builder) { diff --git a/application/src/main/java/run/halo/app/event/post/CounterEvent.java b/application/src/main/java/run/halo/app/event/post/CounterEvent.java new file mode 100644 index 0000000000..58d68b6eae --- /dev/null +++ b/application/src/main/java/run/halo/app/event/post/CounterEvent.java @@ -0,0 +1,18 @@ +package run.halo.app.event.post; + +import org.springframework.context.ApplicationEvent; +import run.halo.app.core.extension.Counter; + +public abstract class CounterEvent extends ApplicationEvent { + + private final Counter counter; + + public CounterEvent(Object source, Counter counter) { + super(source); + this.counter = counter; + } + + public Counter getCounter() { + return counter; + } +} diff --git a/application/src/main/java/run/halo/app/event/post/CounterUpdatedEvent.java b/application/src/main/java/run/halo/app/event/post/CounterUpdatedEvent.java new file mode 100644 index 0000000000..665f4794a1 --- /dev/null +++ b/application/src/main/java/run/halo/app/event/post/CounterUpdatedEvent.java @@ -0,0 +1,9 @@ +package run.halo.app.event.post; + +import run.halo.app.core.extension.Counter; + +public class CounterUpdatedEvent extends CounterEvent { + public CounterUpdatedEvent(Object source, Counter counter) { + super(source, counter); + } +} diff --git a/application/src/main/java/run/halo/app/metrics/PostCounterEventReconciler.java b/application/src/main/java/run/halo/app/metrics/PostCounterEventReconciler.java new file mode 100644 index 0000000000..372a84bff2 --- /dev/null +++ b/application/src/main/java/run/halo/app/metrics/PostCounterEventReconciler.java @@ -0,0 +1,103 @@ +package run.halo.app.metrics; + +import java.time.Duration; +import java.time.Instant; +import org.springframework.context.SmartLifecycle; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import run.halo.app.core.extension.Counter; +import run.halo.app.core.extension.content.Post; +import run.halo.app.event.post.CounterEvent; +import run.halo.app.event.post.CounterUpdatedEvent; +import run.halo.app.extension.ExtensionClient; +import run.halo.app.extension.GroupVersionKind; +import run.halo.app.extension.controller.Controller; +import run.halo.app.extension.controller.ControllerBuilder; +import run.halo.app.extension.controller.DefaultController; +import run.halo.app.extension.controller.DefaultQueue; +import run.halo.app.extension.controller.Reconciler; +import run.halo.app.extension.controller.RequestQueue; +import run.halo.app.extension.index.Indexer; +import run.halo.app.extension.index.IndexerFactoryImpl; +import run.halo.app.infra.utils.JsonUtils; + + +@Component +public class PostCounterEventReconciler implements Reconciler, SmartLifecycle { + private final RequestQueue counterEventQueue; + + private final ExtensionClient client; + + private final IndexerFactoryImpl indexerFactory; + + private volatile boolean running = false; + private final Controller counterEventController; + + public PostCounterEventReconciler(ExtensionClient client, IndexerFactoryImpl indexerFactory) { + this.counterEventQueue = new DefaultQueue<>(Instant::now); + this.client = client; + this.indexerFactory = indexerFactory; + this.counterEventController = this.setupWith(null); + } + + + @Override + public Result reconcile(CounterEvent request) { + if (request instanceof CounterUpdatedEvent) { + updateIndexByPost(request.getCounter(), + getPostName(request.getCounter().getMetadata().getName())); + } + return Result.doNotRetry(); + } + + @Override + public Controller setupWith(ControllerBuilder builder) { + return new DefaultController<>( + this.getClass().getName(), + this, + counterEventQueue, + null, + Duration.ofMillis(300), + Duration.ofMinutes(5)); + } + + private void updateIndexByPost(Counter counter, String postName) { + client.fetch(Post.class, postName) + .ifPresent(post -> { + post.getMetadata().getAnnotations() + .put(Post.COUNTER_ANNO, JsonUtils.objectToJson(counter)); + GroupVersionKind gvk = GroupVersionKind.fromExtension(Post.class); + Indexer indexer = indexerFactory.getIndexer(gvk); + indexer.updateRecord(post); + }); + } + + String getPostName(String name) { + if (name.contains("/")) { + return name.split("/")[1]; + } + return name; + } + + @EventListener(CounterEvent.class) + public void onCounterEvent(CounterEvent counterEvent) { + counterEventQueue.addImmediately(counterEvent); + } + + @Override + public void start() { + this.counterEventController.start(); + this.running = true; + } + + @Override + public void stop() { + this.running = false; + this.counterEventController.dispose(); + } + + @Override + public boolean isRunning() { + return this.running; + } +} From b843a0d3f64e528b83a6ad69893cd1e879e0764b Mon Sep 17 00:00:00 2001 From: ZJamss Date: Tue, 2 Apr 2024 13:28:47 +0800 Subject: [PATCH 6/9] refactored Signed-off-by: ZJamss --- .../halo/app/core/extension/content/Post.java | 2 +- .../main/java/run/halo/app/content/Stats.java | 26 +++-- .../reconciler/PostCounterReconciler.java | 74 ++++--------- .../extension/reconciler/PostReconciler.java | 2 - .../halo/app/event/post/PostChangeEvent.java | 17 --- .../app/event/post/PostStatsChangedEvent.java | 23 ++++ .../run/halo/app/infra/SchemeInitializer.java | 50 ++++----- .../metrics/PostCounterEventReconciler.java | 103 ------------------ .../halo/app/metrics/PostStatsUpdater.java | 90 +++++++++++++++ .../modules/contents/posts/PostList.vue | 4 +- 10 files changed, 180 insertions(+), 211 deletions(-) delete mode 100644 application/src/main/java/run/halo/app/event/post/PostChangeEvent.java create mode 100644 application/src/main/java/run/halo/app/event/post/PostStatsChangedEvent.java delete mode 100644 application/src/main/java/run/halo/app/metrics/PostCounterEventReconciler.java create mode 100644 application/src/main/java/run/halo/app/metrics/PostStatsUpdater.java diff --git a/api/src/main/java/run/halo/app/core/extension/content/Post.java b/api/src/main/java/run/halo/app/core/extension/content/Post.java index 792edc218f..9be8c4129a 100644 --- a/api/src/main/java/run/halo/app/core/extension/content/Post.java +++ b/api/src/main/java/run/halo/app/core/extension/content/Post.java @@ -43,7 +43,7 @@ public class Post extends AbstractExtension { "content.halo.run/last-released-snapshot"; public static final String LAST_ASSOCIATED_TAGS_ANNO = "content.halo.run/last-associated-tags"; - public static final String COUNTER_ANNO = "content.halo.run/counter"; + public static final String STATS_ANNO = "content.halo.run/stats"; public static final String DELETED_LABEL = "content.halo.run/deleted"; public static final String PUBLISHED_LABEL = "content.halo.run/published"; diff --git a/application/src/main/java/run/halo/app/content/Stats.java b/application/src/main/java/run/halo/app/content/Stats.java index 3a3f4fabc6..43f19bfa0c 100644 --- a/application/src/main/java/run/halo/app/content/Stats.java +++ b/application/src/main/java/run/halo/app/content/Stats.java @@ -1,7 +1,7 @@ package run.halo.app.content; import lombok.Builder; -import lombok.Value; +import lombok.Data; /** * Stats value object. @@ -9,17 +9,27 @@ * @author guqing * @since 2.0.0 */ -@Value -@Builder +@Data public class Stats { - Integer visit; + private Integer visit; - Integer upvote; + private Integer upvote; - Integer totalComment; + private Integer totalComment; - Integer approvedComment; + private Integer approvedComment; + + public Stats() { + } + + @Builder + public Stats(Integer visit, Integer upvote, Integer totalComment, Integer approvedComment) { + this.visit = visit; + this.upvote = upvote; + this.totalComment = totalComment; + this.approvedComment = approvedComment; + } public static Stats empty() { return Stats.builder() @@ -29,4 +39,4 @@ public static Stats empty() { .approvedComment(0) .build(); } -} +} \ No newline at end of file diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java index 60cf3c7b33..3c793a4197 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java @@ -1,81 +1,53 @@ package run.halo.app.core.extension.reconciler; -import java.time.Instant; +import static run.halo.app.extension.index.query.QueryFactory.startsWith; + +import lombok.RequiredArgsConstructor; import org.springframework.context.ApplicationEventPublisher; -import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; import run.halo.app.core.extension.Counter; import run.halo.app.core.extension.content.Post; -import run.halo.app.event.post.CounterUpdatedEvent; -import run.halo.app.event.post.PostChangeEvent; +import run.halo.app.event.post.PostStatsChangedEvent; +import run.halo.app.extension.DefaultExtensionMatcher; import run.halo.app.extension.ExtensionClient; import run.halo.app.extension.controller.Controller; import run.halo.app.extension.controller.ControllerBuilder; -import run.halo.app.extension.controller.DefaultQueue; import run.halo.app.extension.controller.Reconciler; -import run.halo.app.extension.controller.RequestQueue; +import run.halo.app.extension.router.selector.FieldSelector; import run.halo.app.metrics.MeterUtils; - @Component +@RequiredArgsConstructor public class PostCounterReconciler implements Reconciler { - private final ExtensionClient client; - private final RequestQueue queue; private final ApplicationEventPublisher eventPublisher; - - - public PostCounterReconciler(ExtensionClient client, - ApplicationEventPublisher eventPublisher) { - this.client = client; - this.eventPublisher = eventPublisher; - this.queue = new DefaultQueue<>(Instant::now); - } + private final ExtensionClient client; @Override public Result reconcile(Request request) { - String name = request.name(); - if (isPostCounter(name)) { - client.fetch(Counter.class, getCounterName(name)).ifPresent(counter -> { - eventPublisher.publishEvent(new CounterUpdatedEvent(this, counter)); - }); + if (!isSameAsPost(request.name())) { + return Result.doNotRetry(); } + client.fetch(Counter.class, request.name()).ifPresent(counter -> { + eventPublisher.publishEvent(new PostStatsChangedEvent(this, counter)); + }); return Result.doNotRetry(); } - @Override public Controller setupWith(ControllerBuilder builder) { + var extension = new Counter(); return builder - .extension(new Counter()) - .syncAllOnStart(true) - .queue(queue) + .extension(extension) + .onAddMatcher(DefaultExtensionMatcher.builder(client, extension.groupVersionKind()) + .fieldSelector(FieldSelector.of( + startsWith("metadata.name", MeterUtils.nameOf(Post.class, ""))) + ) + .build()) .build(); } - @EventListener(PostChangeEvent.class) - public void onPostChanged(PostChangeEvent event) { - queue.addImmediately(new Request(event.getName())); - } - - String getPostName(String name) { - if (name.contains("/")) { - return name.split("/")[1]; - } - return name; - } - - String getCounterName(String name) { - if (name.contains("/")) { - return name; - } - return MeterUtils.nameOf(Post.class, name); - } - - boolean isPostCounter(String counterName) { - if (counterName.contains("/")) { - return MeterUtils.nameOf(Post.class, getPostName(counterName)).equals(counterName); - } - return true; + static boolean isSameAsPost(String name) { + return name.startsWith(MeterUtils.nameOf(Post.class, "")); } -} +} \ No newline at end of file diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostReconciler.java index 8a87e0c2a0..90b01017a4 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PostReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostReconciler.java @@ -33,7 +33,6 @@ import run.halo.app.core.extension.content.Post.VisibleEnum; import run.halo.app.core.extension.content.Snapshot; import run.halo.app.core.extension.notification.Subscription; -import run.halo.app.event.post.PostChangeEvent; import run.halo.app.event.post.PostDeletedEvent; import run.halo.app.event.post.PostPublishedEvent; import run.halo.app.event.post.PostUnpublishedEvent; @@ -84,7 +83,6 @@ public class PostReconciler implements Reconciler { @Override public Result reconcile(Request request) { var events = new HashSet(); - events.add(new PostChangeEvent(this, request.name())); client.fetch(Post.class, request.name()) .ifPresent(post -> { if (ExtensionOperator.isDeleted(post)) { diff --git a/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java b/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java deleted file mode 100644 index 8cc95350bd..0000000000 --- a/application/src/main/java/run/halo/app/event/post/PostChangeEvent.java +++ /dev/null @@ -1,17 +0,0 @@ -package run.halo.app.event.post; - -import org.springframework.context.ApplicationEvent; - -public class PostChangeEvent extends ApplicationEvent implements PostEvent { - private final String name; - - public PostChangeEvent(Object source, String post) { - super(source); - this.name = post; - } - - @Override - public String getName() { - return this.name; - } -} diff --git a/application/src/main/java/run/halo/app/event/post/PostStatsChangedEvent.java b/application/src/main/java/run/halo/app/event/post/PostStatsChangedEvent.java new file mode 100644 index 0000000000..371efc11e5 --- /dev/null +++ b/application/src/main/java/run/halo/app/event/post/PostStatsChangedEvent.java @@ -0,0 +1,23 @@ +package run.halo.app.event.post; + +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.ApplicationEvent; +import run.halo.app.core.extension.Counter; +import run.halo.app.core.extension.content.Post; +import run.halo.app.metrics.MeterUtils; + +@Getter +public class PostStatsChangedEvent extends ApplicationEvent { + private final Counter counter; + + public PostStatsChangedEvent(Object source, Counter counter) { + super(source); + this.counter = counter; + } + + public String getPostName() { + var counterName = counter.getMetadata().getName(); + return StringUtils.removeStart(counterName, MeterUtils.nameOf(Post.class, "")); + } +} \ No newline at end of file diff --git a/application/src/main/java/run/halo/app/infra/SchemeInitializer.java b/application/src/main/java/run/halo/app/infra/SchemeInitializer.java index ade5e9eac0..da1ff8a4f1 100644 --- a/application/src/main/java/run/halo/app/infra/SchemeInitializer.java +++ b/application/src/main/java/run/halo/app/infra/SchemeInitializer.java @@ -9,11 +9,13 @@ import com.fasterxml.jackson.core.type.TypeReference; import java.util.Set; import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.boot.context.event.ApplicationContextInitializedEvent; import org.springframework.context.ApplicationListener; import org.springframework.lang.NonNull; import org.springframework.stereotype.Component; +import run.halo.app.content.Stats; import run.halo.app.core.extension.AnnotationSetting; import run.halo.app.core.extension.AuthProvider; import run.halo.app.core.extension.Counter; @@ -184,34 +186,28 @@ public void onApplicationEvent(@NonNull ApplicationContextInitializedEvent event }))); indexSpecs.add(new IndexSpec() - .setName("counter.visit") - .setIndexFunc( - simpleAttribute(Post.class, - post -> { - String counterJson = - post.getMetadata().getAnnotations().get(Post.COUNTER_ANNO); - if (counterJson != null) { - return JsonUtils.jsonToObject(counterJson, Counter.class) - .getVisit().toString(); - } - return "0"; - } - ))); + .setName("stats.visit") + .setIndexFunc(simpleAttribute(Post.class, post -> { + var annotations = MetadataUtil.nullSafeAnnotations(post); + var statsStr = annotations.get(Post.STATS_ANNO); + if (StringUtils.isBlank(statsStr)) { + return "0"; + } + var stats = JsonUtils.jsonToObject(statsStr, Stats.class); + return ObjectUtils.defaultIfNull(stats.getVisit(), 0).toString(); + }))); indexSpecs.add(new IndexSpec() - .setName("counter.comment") - .setIndexFunc( - simpleAttribute(Post.class, - post -> { - String counterJson = - post.getMetadata().getAnnotations().get(Post.COUNTER_ANNO); - if (counterJson != null) { - return JsonUtils.jsonToObject(counterJson, Counter.class) - .getTotalComment().toString(); - } - return "0"; - } - ))); + .setName("stats.totalComment") + .setIndexFunc(simpleAttribute(Post.class, post -> { + var annotations = MetadataUtil.nullSafeAnnotations(post); + var statsStr = annotations.get(Post.STATS_ANNO); + if (StringUtils.isBlank(statsStr)) { + return "0"; + } + var stats = JsonUtils.jsonToObject(statsStr, Stats.class); + return ObjectUtils.defaultIfNull(stats.getTotalComment(), 0).toString(); + }))); }); schemeManager.register(Category.class, indexSpecs -> { indexSpecs.add(new IndexSpec() @@ -460,4 +456,4 @@ private static DefaultSchemeManager createSchemeManager( beanFactory.registerSingleton("schemeManager", schemeManager); return schemeManager; } -} +} \ No newline at end of file diff --git a/application/src/main/java/run/halo/app/metrics/PostCounterEventReconciler.java b/application/src/main/java/run/halo/app/metrics/PostCounterEventReconciler.java deleted file mode 100644 index 372a84bff2..0000000000 --- a/application/src/main/java/run/halo/app/metrics/PostCounterEventReconciler.java +++ /dev/null @@ -1,103 +0,0 @@ -package run.halo.app.metrics; - -import java.time.Duration; -import java.time.Instant; -import org.springframework.context.SmartLifecycle; -import org.springframework.context.event.EventListener; -import org.springframework.stereotype.Component; -import run.halo.app.core.extension.Counter; -import run.halo.app.core.extension.content.Post; -import run.halo.app.event.post.CounterEvent; -import run.halo.app.event.post.CounterUpdatedEvent; -import run.halo.app.extension.ExtensionClient; -import run.halo.app.extension.GroupVersionKind; -import run.halo.app.extension.controller.Controller; -import run.halo.app.extension.controller.ControllerBuilder; -import run.halo.app.extension.controller.DefaultController; -import run.halo.app.extension.controller.DefaultQueue; -import run.halo.app.extension.controller.Reconciler; -import run.halo.app.extension.controller.RequestQueue; -import run.halo.app.extension.index.Indexer; -import run.halo.app.extension.index.IndexerFactoryImpl; -import run.halo.app.infra.utils.JsonUtils; - - -@Component -public class PostCounterEventReconciler implements Reconciler, SmartLifecycle { - private final RequestQueue counterEventQueue; - - private final ExtensionClient client; - - private final IndexerFactoryImpl indexerFactory; - - private volatile boolean running = false; - private final Controller counterEventController; - - public PostCounterEventReconciler(ExtensionClient client, IndexerFactoryImpl indexerFactory) { - this.counterEventQueue = new DefaultQueue<>(Instant::now); - this.client = client; - this.indexerFactory = indexerFactory; - this.counterEventController = this.setupWith(null); - } - - - @Override - public Result reconcile(CounterEvent request) { - if (request instanceof CounterUpdatedEvent) { - updateIndexByPost(request.getCounter(), - getPostName(request.getCounter().getMetadata().getName())); - } - return Result.doNotRetry(); - } - - @Override - public Controller setupWith(ControllerBuilder builder) { - return new DefaultController<>( - this.getClass().getName(), - this, - counterEventQueue, - null, - Duration.ofMillis(300), - Duration.ofMinutes(5)); - } - - private void updateIndexByPost(Counter counter, String postName) { - client.fetch(Post.class, postName) - .ifPresent(post -> { - post.getMetadata().getAnnotations() - .put(Post.COUNTER_ANNO, JsonUtils.objectToJson(counter)); - GroupVersionKind gvk = GroupVersionKind.fromExtension(Post.class); - Indexer indexer = indexerFactory.getIndexer(gvk); - indexer.updateRecord(post); - }); - } - - String getPostName(String name) { - if (name.contains("/")) { - return name.split("/")[1]; - } - return name; - } - - @EventListener(CounterEvent.class) - public void onCounterEvent(CounterEvent counterEvent) { - counterEventQueue.addImmediately(counterEvent); - } - - @Override - public void start() { - this.counterEventController.start(); - this.running = true; - } - - @Override - public void stop() { - this.running = false; - this.counterEventController.dispose(); - } - - @Override - public boolean isRunning() { - return this.running; - } -} diff --git a/application/src/main/java/run/halo/app/metrics/PostStatsUpdater.java b/application/src/main/java/run/halo/app/metrics/PostStatsUpdater.java new file mode 100644 index 0000000000..de0ae43264 --- /dev/null +++ b/application/src/main/java/run/halo/app/metrics/PostStatsUpdater.java @@ -0,0 +1,90 @@ +package run.halo.app.metrics; + +import java.time.Duration; +import java.time.Instant; +import org.springframework.context.SmartLifecycle; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import run.halo.app.content.Stats; +import run.halo.app.core.extension.content.Post; +import run.halo.app.event.post.PostStatsChangedEvent; +import run.halo.app.extension.ExtensionClient; +import run.halo.app.extension.MetadataUtil; +import run.halo.app.extension.controller.Controller; +import run.halo.app.extension.controller.ControllerBuilder; +import run.halo.app.extension.controller.DefaultController; +import run.halo.app.extension.controller.DefaultQueue; +import run.halo.app.extension.controller.Reconciler; +import run.halo.app.extension.controller.RequestQueue; +import run.halo.app.infra.utils.JsonUtils; + +@Component +public class PostStatsUpdater implements Reconciler, + SmartLifecycle { + + private volatile boolean running = false; + + private final ExtensionClient client; + private final RequestQueue queue; + private final Controller controller; + + public PostStatsUpdater(ExtensionClient client) { + this.client = client; + queue = new DefaultQueue<>(Instant::now); + controller = this.setupWith(null); + } + + @Override + public Result reconcile(StatsRequest request) { + client.fetch(Post.class, request.postName()).ifPresent(post -> { + var annotations = MetadataUtil.nullSafeAnnotations(post); + annotations.put(Post.STATS_ANNO, JsonUtils.objectToJson(request.stats())); + client.update(post); + }); + return Result.doNotRetry(); + } + + @Override + public Controller setupWith(ControllerBuilder builder) { + return new DefaultController<>( + this.getClass().getName(), + this, + queue, + null, + Duration.ofMillis(100), + Duration.ofMinutes(10)); + } + + @Override + public void start() { + this.controller.start(); + this.running = true; + } + + @Override + public void stop() { + this.running = false; + this.controller.dispose(); + } + + @Override + public boolean isRunning() { + return this.running; + } + + @EventListener(PostStatsChangedEvent.class) + public void onReplyEvent(PostStatsChangedEvent event) { + var counter = event.getCounter(); + var stats = Stats.builder() + .visit(counter.getVisit()) + .upvote(counter.getUpvote()) + .totalComment(counter.getTotalComment()) + .approvedComment(counter.getApprovedComment()) + .build(); + var request = new StatsRequest(event.getPostName(), stats); + queue.addImmediately(request); + } + + public record StatsRequest(String postName, Stats stats) { + } +} \ No newline at end of file diff --git a/ui/console-src/modules/contents/posts/PostList.vue b/ui/console-src/modules/contents/posts/PostList.vue index c3d403c6b1..094584613d 100644 --- a/ui/console-src/modules/contents/posts/PostList.vue +++ b/ui/console-src/modules/contents/posts/PostList.vue @@ -422,11 +422,11 @@ watch(selectedPostNames, (newValue) => { }, { label: t('core.post.filters.sort.items.visit_desc'), - value: 'counter.visit,desc', + value: 'stats.visit,desc', }, { label: t('core.post.filters.sort.items.comment_desc'), - value: 'counter.comment,desc', + value: 'stats.totalComment,desc', }, ]" /> From 39f5cac4e58961c4e14b77fdf84081fc3f9a9453 Mon Sep 17 00:00:00 2001 From: ZJamss Date: Tue, 2 Apr 2024 15:28:05 +0800 Subject: [PATCH 7/9] removed unused code Signed-off-by: ZJamss --- .../run/halo/app/event/post/CounterEvent.java | 18 ------------------ .../app/event/post/CounterUpdatedEvent.java | 9 --------- 2 files changed, 27 deletions(-) delete mode 100644 application/src/main/java/run/halo/app/event/post/CounterEvent.java delete mode 100644 application/src/main/java/run/halo/app/event/post/CounterUpdatedEvent.java diff --git a/application/src/main/java/run/halo/app/event/post/CounterEvent.java b/application/src/main/java/run/halo/app/event/post/CounterEvent.java deleted file mode 100644 index 58d68b6eae..0000000000 --- a/application/src/main/java/run/halo/app/event/post/CounterEvent.java +++ /dev/null @@ -1,18 +0,0 @@ -package run.halo.app.event.post; - -import org.springframework.context.ApplicationEvent; -import run.halo.app.core.extension.Counter; - -public abstract class CounterEvent extends ApplicationEvent { - - private final Counter counter; - - public CounterEvent(Object source, Counter counter) { - super(source); - this.counter = counter; - } - - public Counter getCounter() { - return counter; - } -} diff --git a/application/src/main/java/run/halo/app/event/post/CounterUpdatedEvent.java b/application/src/main/java/run/halo/app/event/post/CounterUpdatedEvent.java deleted file mode 100644 index 665f4794a1..0000000000 --- a/application/src/main/java/run/halo/app/event/post/CounterUpdatedEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package run.halo.app.event.post; - -import run.halo.app.core.extension.Counter; - -public class CounterUpdatedEvent extends CounterEvent { - public CounterUpdatedEvent(Object source, Counter counter) { - super(source, counter); - } -} From a674e420c19030436c7442a11e755f4ed56c32b7 Mon Sep 17 00:00:00 2001 From: ZJamss Date: Thu, 4 Apr 2024 23:12:26 +0800 Subject: [PATCH 8/9] check style Signed-off-by: ZJamss --- .../app/extension/controller/ControllerBuilder.java | 11 ++--------- .../src/main/java/run/halo/app/content/Stats.java | 2 +- .../extension/reconciler/PostCounterReconciler.java | 2 +- .../halo/app/event/post/PostStatsChangedEvent.java | 2 +- .../java/run/halo/app/infra/SchemeInitializer.java | 2 +- .../java/run/halo/app/metrics/PostStatsUpdater.java | 2 +- 6 files changed, 7 insertions(+), 14 deletions(-) diff --git a/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java b/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java index 417a36a757..3e62bbde10 100644 --- a/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java +++ b/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java @@ -35,7 +35,6 @@ public class ControllerBuilder { private boolean syncAllOnStart = true; private int workerCount = 1; - private RequestQueue queue; public ControllerBuilder(Reconciler reconciler, ExtensionClient client) { Assert.notNull(reconciler, "Reconciler must not be null"); @@ -90,11 +89,6 @@ public ControllerBuilder workerCount(int workerCount) { return this; } - public ControllerBuilder queue(RequestQueue queue) { - this.queue = queue; - return this; - } - public Controller build() { if (nowSupplier == null) { nowSupplier = Instant::now; @@ -110,9 +104,8 @@ public Controller build() { Assert.notNull(extension, "Extension must not be null"); Assert.notNull(reconciler, "Reconciler must not be null"); - if (queue == null) { - queue = new DefaultQueue<>(nowSupplier, minDelay); - } + var queue = new DefaultQueue(nowSupplier, minDelay); + var extensionMatchers = WatcherExtensionMatchers.builder(client, extension.groupVersionKind()) .onAddMatcher(onAddMatcher) diff --git a/application/src/main/java/run/halo/app/content/Stats.java b/application/src/main/java/run/halo/app/content/Stats.java index 43f19bfa0c..151f92689f 100644 --- a/application/src/main/java/run/halo/app/content/Stats.java +++ b/application/src/main/java/run/halo/app/content/Stats.java @@ -39,4 +39,4 @@ public static Stats empty() { .approvedComment(0) .build(); } -} \ No newline at end of file +} diff --git a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java index 3c793a4197..a6986a54c7 100644 --- a/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java +++ b/application/src/main/java/run/halo/app/core/extension/reconciler/PostCounterReconciler.java @@ -50,4 +50,4 @@ public Controller setupWith(ControllerBuilder builder) { static boolean isSameAsPost(String name) { return name.startsWith(MeterUtils.nameOf(Post.class, "")); } -} \ No newline at end of file +} diff --git a/application/src/main/java/run/halo/app/event/post/PostStatsChangedEvent.java b/application/src/main/java/run/halo/app/event/post/PostStatsChangedEvent.java index 371efc11e5..aa936b821d 100644 --- a/application/src/main/java/run/halo/app/event/post/PostStatsChangedEvent.java +++ b/application/src/main/java/run/halo/app/event/post/PostStatsChangedEvent.java @@ -20,4 +20,4 @@ public String getPostName() { var counterName = counter.getMetadata().getName(); return StringUtils.removeStart(counterName, MeterUtils.nameOf(Post.class, "")); } -} \ No newline at end of file +} diff --git a/application/src/main/java/run/halo/app/infra/SchemeInitializer.java b/application/src/main/java/run/halo/app/infra/SchemeInitializer.java index da1ff8a4f1..c5fdf462bf 100644 --- a/application/src/main/java/run/halo/app/infra/SchemeInitializer.java +++ b/application/src/main/java/run/halo/app/infra/SchemeInitializer.java @@ -456,4 +456,4 @@ private static DefaultSchemeManager createSchemeManager( beanFactory.registerSingleton("schemeManager", schemeManager); return schemeManager; } -} \ No newline at end of file +} diff --git a/application/src/main/java/run/halo/app/metrics/PostStatsUpdater.java b/application/src/main/java/run/halo/app/metrics/PostStatsUpdater.java index de0ae43264..f417c6e1ca 100644 --- a/application/src/main/java/run/halo/app/metrics/PostStatsUpdater.java +++ b/application/src/main/java/run/halo/app/metrics/PostStatsUpdater.java @@ -87,4 +87,4 @@ public void onReplyEvent(PostStatsChangedEvent event) { public record StatsRequest(String postName, Stats stats) { } -} \ No newline at end of file +} From b5cd2d13fc9992c62d52820bbf5223994d9866dc Mon Sep 17 00:00:00 2001 From: ZJamss Date: Thu, 4 Apr 2024 23:49:02 +0800 Subject: [PATCH 9/9] check Signed-off-by: ZJamss --- .../run/halo/app/extension/controller/ControllerBuilder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java b/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java index 3e62bbde10..2bfcd9c4c4 100644 --- a/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java +++ b/api/src/main/java/run/halo/app/extension/controller/ControllerBuilder.java @@ -105,7 +105,6 @@ public Controller build() { Assert.notNull(reconciler, "Reconciler must not be null"); var queue = new DefaultQueue(nowSupplier, minDelay); - var extensionMatchers = WatcherExtensionMatchers.builder(client, extension.groupVersionKind()) .onAddMatcher(onAddMatcher)