Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
ruibaby committed Mar 17, 2024
2 parents cac0163 + 5e073bf commit 496847d
Show file tree
Hide file tree
Showing 71 changed files with 1,497 additions and 882 deletions.
7 changes: 6 additions & 1 deletion api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ plugins {
id 'java-library'
id 'halo.publish'
id 'jacoco'
id "io.freefair.lombok" version "8.4"
id "io.freefair.lombok"
}

group = 'run.halo.app'
description = 'API of halo project, connecting by other projects.'

java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

compileJava.options.encoding = "UTF-8"
compileTestJava.options.encoding = "UTF-8"
javadoc.options.encoding = "UTF-8"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ public class Post extends AbstractExtension {
public static final String CATEGORIES_ANNO = "content.halo.run/categories";
public static final String LAST_RELEASED_SNAPSHOT_ANNO =
"content.halo.run/last-released-snapshot";
public static final String TAGS_ANNO = "content.halo.run/tags";
public static final String LAST_ASSOCIATED_TAGS_ANNO = "content.halo.run/last-associated-tags";

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
Expand Up @@ -27,6 +27,8 @@ public class Tag extends AbstractExtension {

public static final GroupVersionKind GVK = GroupVersionKind.fromExtension(Tag.class);

public static final String REQUIRE_SYNC_ON_STARTUP_INDEX_NAME = "requireSyncOnStartup";

@Schema(requiredMode = REQUIRED)
private TagSpec spec;

Expand Down Expand Up @@ -77,5 +79,7 @@ public static class TagStatus {
public Integer visiblePostCount;

public Integer postCount;

private Long observedVersion;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static Query and(Collection<Query> queries) {
return new And(queries);
}

public static Query and(Query query1, Query query2) {
public static And and(Query query1, Query query2) {
Collection<Query> queries = Arrays.asList(query1, query2);
return new And(queries);
}
Expand Down
17 changes: 8 additions & 9 deletions application/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,24 @@ import de.undercouch.gradle.tasks.download.Download
import org.gradle.crypto.checksum.Checksum

plugins {
id 'org.springframework.boot' version '3.2.3'
id 'io.spring.dependency-management' version '1.1.0'
id "com.gorylenko.gradle-git-properties" version "2.3.2"
id 'org.springframework.boot'
id 'io.spring.dependency-management'
id "com.gorylenko.gradle-git-properties"
id "checkstyle"
id 'java'
id 'jacoco'
id "de.undercouch.download" version "5.3.1"
id "io.freefair.lombok" version "8.4"
id 'org.gradle.crypto.checksum' version '1.4.0'
id "de.undercouch.download"
id "io.freefair.lombok"
id 'org.gradle.crypto.checksum'
}

group = 'run.halo.app'
compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

checkstyle {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Data;
import lombok.experimental.Accessors;
import run.halo.app.core.extension.content.Category;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.Tag;
Expand All @@ -17,6 +18,7 @@
* @since 2.0.0
*/
@Data
@Accessors(chain = true)
public class ListedPost {

@Schema(requiredMode = REQUIRED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Data;
import lombok.experimental.Accessors;
import run.halo.app.core.extension.content.SinglePage;


Expand All @@ -15,6 +16,7 @@
* @since 2.0.0
*/
@Data
@Accessors(chain = true)
public class ListedSinglePage {

@Schema(requiredMode = REQUIRED)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
package run.halo.app.content;

import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
import static run.halo.app.extension.index.query.QueryFactory.and;
import static run.halo.app.extension.index.query.QueryFactory.equal;
import static run.halo.app.extension.index.query.QueryFactory.isNull;

import com.google.common.collect.Sets;
import java.time.Duration;
import java.time.Instant;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.Tag;
import run.halo.app.core.extension.content.Tag.TagStatus;
import run.halo.app.event.post.PostDeletedEvent;
import run.halo.app.event.post.PostEvent;
import run.halo.app.event.post.PostUpdatedEvent;
import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.PageRequestImpl;
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.router.selector.FieldSelector;
import run.halo.app.extension.router.selector.LabelSelector;
import run.halo.app.infra.utils.JsonUtils;

/**
* Update {@link TagStatus#postCount} when post related to tag is updated.
*
* @author guqing
* @since 2.13.0
*/
@Component
public class TagPostCountUpdater
implements Reconciler<TagPostCountUpdater.PostRelatedTags>, SmartLifecycle {

private final RequestQueue<PostRelatedTags> tagQueue;

private final Controller postEventController;

private final ExtensionClient client;

private volatile boolean running = false;

/**
* Construct a {@link TagPostCountUpdater} with the given {@link ExtensionClient}.
*/
public TagPostCountUpdater(ExtensionClient client) {
this.client = client;

this.tagQueue = new DefaultQueue<>(Instant::now);
this.postEventController = this.setupWith(null);
}

@Override
public Result reconcile(PostRelatedTags postRelatedTags) {
for (var tag : postRelatedTags.tags()) {
updateTagRelatedPostCount(tag);
}

// Update last associated tags when handled
client.fetch(Post.class, postRelatedTags.postName()).ifPresent(post -> {
var tags = defaultIfNull(post.getSpec().getTags(), List.<String>of());
var annotations = MetadataUtil.nullSafeAnnotations(post);
var tagAnno = JsonUtils.objectToJson(tags);
var oldTagAnno = annotations.get(Post.LAST_ASSOCIATED_TAGS_ANNO);

if (!tagAnno.equals(oldTagAnno)) {
annotations.put(Post.LAST_ASSOCIATED_TAGS_ANNO, tagAnno);
client.update(post);
}
});
return Result.doNotRetry();
}


@Override
public Controller setupWith(ControllerBuilder builder) {
return new DefaultController<>(
this.getClass().getName(),
this,
tagQueue,
null,
Duration.ofMillis(100),
Duration.ofMinutes(10)
);
}

@Override
public void start() {
postEventController.start();
running = true;
}

@Override
public void stop() {
running = false;
postEventController.dispose();
}

@Override
public boolean isRunning() {
return running;
}

/**
* Listen to post event to calculate post related to tag for updating.
*/
@EventListener(PostEvent.class)
public void onPostUpdated(PostEvent postEvent) {
var postName = postEvent.getName();
if (postEvent instanceof PostUpdatedEvent) {
var tagsToUpdate = calcTagsToUpdate(postEvent.getName());
tagQueue.addImmediately(new PostRelatedTags(postName, tagsToUpdate));
return;
}

if (postEvent instanceof PostDeletedEvent deletedEvent) {
var tags = defaultIfNull(deletedEvent.getPost().getSpec().getTags(),
List.<String>of());
tagQueue.addImmediately(new PostRelatedTags(postName, Sets.newHashSet(tags)));
}
}

private Set<String> calcTagsToUpdate(String postName) {
var post = client.fetch(Post.class, postName).orElseThrow();
var annotations = MetadataUtil.nullSafeAnnotations(post);
var oldTags = Optional.ofNullable(annotations.get(Post.LAST_ASSOCIATED_TAGS_ANNO))
.filter(StringUtils::isNotBlank)
.map(tagsJson -> JsonUtils.jsonToObject(tagsJson, String[].class))
.orElse(new String[0]);

var tagsToUpdate = Sets.newHashSet(oldTags);
var newTags = post.getSpec().getTags();
if (newTags != null) {
tagsToUpdate.addAll(newTags);
}
return tagsToUpdate;
}

public record PostRelatedTags(String postName, Set<String> tags) {
}

private void updateTagRelatedPostCount(String tagName) {
client.fetch(Tag.class, tagName).ifPresent(tag -> {
var commonFieldQuery = and(
equal("spec.tags", tag.getMetadata().getName()),
isNull("metadata.deletionTimestamp")
);
// Update post count
var allPostOptions = new ListOptions();
allPostOptions.setFieldSelector(FieldSelector.of(commonFieldQuery));
var result = client.listBy(Post.class, allPostOptions, PageRequestImpl.ofSize(1));
tag.getStatusOrDefault().setPostCount((int) result.getTotal());

// Update visible post count
var publicPostOptions = new ListOptions();
publicPostOptions.setLabelSelector(LabelSelector.builder()
.eq(Post.PUBLISHED_LABEL, "true")
.build());
publicPostOptions.setFieldSelector(FieldSelector.of(
and(
commonFieldQuery,
equal("spec.deleted", "false"),
equal("spec.visible", Post.VisibleEnum.PUBLIC.name())
)
));
var publicPosts =
client.listBy(Post.class, publicPostOptions, PageRequestImpl.ofSize(1));
tag.getStatusOrDefault().setVisiblePostCount((int) publicPosts.getTotal());

client.update(tag);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,16 @@ public String getOwnerName() {
@ArraySchema(uniqueItems = true,
arraySchema = @Schema(name = "sort",
description = "Sort property and direction of the list result. Supported fields: "
+ "creationTimestamp,replyCount,lastReplyTime"),
+ "metadata.creationTimestamp,status.replyCount,status.lastReplyTime"),
schema = @Schema(description = "like field,asc or field,desc",
implementation = String.class,
example = "creationTimestamp,desc"))
public Sort getSort() {
var sort = SortResolver.defaultInstance.resolve(exchange);
return sort.and(Sort.by("spec.creationTime", "metadata.name").descending());
return sort.and(Sort.by("status.lastReplyTime",
"spec.creationTime",
"metadata.name"
).descending());
}

public PageRequest toPageRequest() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package run.halo.app.content.comment;

import org.springframework.lang.NonNull;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.content.Comment;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.Ref;

/**
* An application service for {@link Comment}.
Expand All @@ -15,4 +17,6 @@ public interface CommentService {
Mono<ListResult<ListedComment>> listComment(CommentQuery query);

Mono<Comment> create(Comment comment);

Mono<Void> removeBySubject(@NonNull Ref subjectRef);
}
Loading

0 comments on commit 496847d

Please sign in to comment.