Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support sorting posts by views and comment count #5614

Merged
merged 15 commits into from
Apr 11, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -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";
ZJamss marked this conversation as resolved.
Show resolved Hide resolved
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";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
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;
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;


@Component
public class PostCounterReconciler implements Reconciler<Reconciler.Request> {

private final ExtensionClient client;

private final IndexerFactoryImpl indexerFactory;

private final Set<String> 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));
ZJamss marked this conversation as resolved.
Show resolved Hide resolved
});
return Result.doNotRetry();
}


@Scheduled(cron = "0/3 * * * * ?")
public void handleSetRequest() {
ZJamss marked this conversation as resolved.
Show resolved Hide resolved
Iterator<String> 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)
ZJamss marked this conversation as resolved.
Show resolved Hide resolved
.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() {
ZJamss marked this conversation as resolved.
Show resolved Hide resolved
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];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -83,6 +84,7 @@ public class PostReconciler implements Reconciler<Reconciler.Request> {
@Override
public Result reconcile(Request request) {
var events = new HashSet<ApplicationEvent>();
events.add(new PostChangeEvent(this, request.name()));
client.fetch(Post.class, request.name())
.ifPresent(post -> {
if (ExtensionOperator.isDeleted(post)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package run.halo.app.event.post;

import org.springframework.context.ApplicationEvent;

public class PostChangeEvent extends ApplicationEvent implements PostEvent {
ZJamss marked this conversation as resolved.
Show resolved Hide resolved
private final String name;

public PostChangeEvent(Object source, String post) {
super(source);
this.name = post;
}

@Override
public String getName() {
return this.name;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
8 changes: 8 additions & 0 deletions ui/console-src/modules/contents/posts/PostList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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',
},
]"
/>
<div class="flex flex-row gap-2">
Expand Down
2 changes: 2 additions & 0 deletions ui/src/locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:"
Expand Down
2 changes: 2 additions & 0 deletions ui/src/locales/es.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:"
Expand Down
2 changes: 2 additions & 0 deletions ui/src/locales/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ core:
publish_time_asc: 较早发布
create_time_desc: 较近创建
create_time_asc: 较早创建
visit_desc: 最多访问量
comment_desc: 最多评论量
list:
fields:
categories: 分类:
Expand Down
2 changes: 2 additions & 0 deletions ui/src/locales/zh-TW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ core:
publish_time_asc: 較早發布
create_time_desc: 較近創建
create_time_asc: 較早創建
visit_desc: 最多訪問量
comment_desc: 最多評論量
list:
fields:
categories: 分類:
Expand Down