mirror of https://github.com/halo-dev/halo
refactor: optimize reply queries using index mechanisms (#5497)
#### What type of PR is this? /kind improvement /area core /milestone 2.14.x #### What this PR does / why we need it: 使用索引机制优化回复功能的查询以提高查询速度 #### Does this PR introduce a user-facing change? ```release-note 使用索引机制优化回复功能的查询以提高查询速度 ```pull/5504/head
parent
956f4ef3f3
commit
e704e09807
|
@ -56,13 +56,16 @@ public class CommentQuery extends IListRequest.QueryListRequest {
|
|||
@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() {
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
package run.halo.app.content.comment;
|
||||
|
||||
import static run.halo.app.extension.index.query.QueryFactory.equal;
|
||||
import static run.halo.app.extension.router.selector.SelectorUtil.labelAndFieldSelectorToListOptions;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.ServerWebInputException;
|
||||
import run.halo.app.core.extension.content.Reply;
|
||||
import run.halo.app.extension.router.IListRequest;
|
||||
import run.halo.app.extension.ListOptions;
|
||||
import run.halo.app.extension.PageRequest;
|
||||
import run.halo.app.extension.PageRequestImpl;
|
||||
import run.halo.app.extension.router.SortableRequest;
|
||||
|
||||
/**
|
||||
* Query criteria for {@link Reply} list.
|
||||
|
@ -12,15 +20,35 @@ import run.halo.app.extension.router.IListRequest;
|
|||
* @author guqing
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ReplyQuery extends IListRequest.QueryListRequest {
|
||||
public class ReplyQuery extends SortableRequest {
|
||||
|
||||
public ReplyQuery(MultiValueMap<String, String> queryParams) {
|
||||
super(queryParams);
|
||||
public ReplyQuery(ServerWebExchange exchange) {
|
||||
super(exchange);
|
||||
}
|
||||
|
||||
@Schema(description = "Replies filtered by commentName.")
|
||||
public String getCommentName() {
|
||||
String commentName = queryParams.getFirst("commentName");
|
||||
return StringUtils.isBlank(commentName) ? null : commentName;
|
||||
if (StringUtils.isBlank(commentName)) {
|
||||
throw new ServerWebInputException("The required parameter 'commentName' is missing.");
|
||||
}
|
||||
return commentName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build list options from query criteria.
|
||||
*/
|
||||
public ListOptions toListOptions() {
|
||||
var listOptions =
|
||||
labelAndFieldSelectorToListOptions(getLabelSelector(), getFieldSelector());
|
||||
var newFieldSelector = listOptions.getFieldSelector()
|
||||
.andQuery(equal("spec.commentName", getCommentName()));
|
||||
listOptions.setFieldSelector(newFieldSelector);
|
||||
return listOptions;
|
||||
}
|
||||
|
||||
public PageRequest toPageRequest() {
|
||||
var sort = getSort().and(Sort.by("spec.creationTime").ascending());
|
||||
return PageRequestImpl.of(getPage(), getSize(), sort);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,9 +79,7 @@ public class ReplyServiceImpl implements ReplyService {
|
|||
|
||||
@Override
|
||||
public Mono<ListResult<ListedReply>> list(ReplyQuery query) {
|
||||
return client.list(Reply.class, getReplyPredicate(query),
|
||||
ReplyService.creationTimeAscComparator(),
|
||||
query.getPage(), query.getSize())
|
||||
return client.listBy(Reply.class, query.toListOptions(), query.toPageRequest())
|
||||
.flatMap(list -> Flux.fromStream(list.get()
|
||||
.map(this::toListedReply))
|
||||
.concatMap(Function.identity())
|
||||
|
|
|
@ -48,7 +48,7 @@ public class ReplyEndpoint implements CustomEndpoint {
|
|||
}
|
||||
|
||||
Mono<ServerResponse> listReplies(ServerRequest request) {
|
||||
ReplyQuery replyQuery = new ReplyQuery(request.queryParams());
|
||||
ReplyQuery replyQuery = new ReplyQuery(request.exchange());
|
||||
return replyService.list(replyQuery)
|
||||
.flatMap(listedReplies -> ServerResponse.ok().bodyValue(listedReplies));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package run.halo.app.core.extension.reconciler;
|
||||
|
||||
import static org.apache.commons.lang3.ObjectUtils.defaultIfNull;
|
||||
import static run.halo.app.extension.ExtensionUtil.addFinalizers;
|
||||
|
||||
import java.util.Set;
|
||||
|
@ -45,6 +46,15 @@ public class ReplyReconciler implements Reconciler<Reconciler.Request> {
|
|||
eventPublisher.publishEvent(new ReplyCreatedEvent(this, reply));
|
||||
}
|
||||
|
||||
if (reply.getSpec().getCreationTime() == null) {
|
||||
reply.getSpec().setCreationTime(
|
||||
defaultIfNull(reply.getSpec().getApprovedTime(),
|
||||
reply.getMetadata().getCreationTimestamp()
|
||||
)
|
||||
);
|
||||
}
|
||||
client.update(reply);
|
||||
|
||||
replyNotificationSubscriptionHelper.subscribeNewReplyReasonForReply(reply);
|
||||
|
||||
eventPublisher.publishEvent(new ReplyChangedEvent(this, reply));
|
||||
|
|
|
@ -223,7 +223,8 @@ public class SchemeInitializer implements ApplicationListener<ApplicationContext
|
|||
indexSpecs.add(new IndexSpec()
|
||||
.setName("spec.creationTime")
|
||||
.setIndexFunc(simpleAttribute(Comment.class,
|
||||
comment -> comment.getSpec().getCreationTime().toString())
|
||||
comment -> defaultIfNull(comment.getSpec().getCreationTime(),
|
||||
comment.getMetadata().getCreationTimestamp()).toString())
|
||||
));
|
||||
indexSpecs.add(new IndexSpec()
|
||||
.setName("spec.approved")
|
||||
|
@ -282,7 +283,35 @@ public class SchemeInitializer implements ApplicationListener<ApplicationContext
|
|||
return defaultIfNull(replyCount, 0).toString();
|
||||
})));
|
||||
});
|
||||
schemeManager.register(Reply.class);
|
||||
schemeManager.register(Reply.class, indexSpecs -> {
|
||||
indexSpecs.add(new IndexSpec()
|
||||
.setName("spec.creationTime")
|
||||
.setIndexFunc(simpleAttribute(Reply.class,
|
||||
reply -> defaultIfNull(reply.getSpec().getCreationTime(),
|
||||
reply.getMetadata().getCreationTimestamp()).toString())
|
||||
));
|
||||
indexSpecs.add(new IndexSpec()
|
||||
.setName("spec.commentName")
|
||||
.setIndexFunc(simpleAttribute(Reply.class,
|
||||
reply -> reply.getSpec().getCommentName())
|
||||
));
|
||||
indexSpecs.add(new IndexSpec()
|
||||
.setName("spec.hidden")
|
||||
.setIndexFunc(simpleAttribute(Reply.class,
|
||||
reply -> toStringTrueFalse(isTrue(reply.getSpec().getHidden())))
|
||||
));
|
||||
indexSpecs.add(new IndexSpec()
|
||||
.setName("spec.approved")
|
||||
.setIndexFunc(simpleAttribute(Reply.class,
|
||||
reply -> toStringTrueFalse(isTrue(reply.getSpec().getApproved())))
|
||||
));
|
||||
indexSpecs.add(new IndexSpec()
|
||||
.setName("spec.owner")
|
||||
.setIndexFunc(simpleAttribute(Reply.class, reply -> {
|
||||
var owner = reply.getSpec().getOwner();
|
||||
return Comment.CommentOwner.ownerIdentity(owner.getKind(), owner.getName());
|
||||
})));
|
||||
});
|
||||
schemeManager.register(SinglePage.class);
|
||||
// storage.halo.run
|
||||
schemeManager.register(Group.class);
|
||||
|
|
|
@ -1,28 +1,35 @@
|
|||
package run.halo.app.metrics;
|
||||
|
||||
import static org.apache.commons.lang3.BooleanUtils.isFalse;
|
||||
import static org.apache.commons.lang3.BooleanUtils.isTrue;
|
||||
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.greaterThan;
|
||||
import static run.halo.app.extension.index.query.QueryFactory.isNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
import run.halo.app.content.comment.ReplyService;
|
||||
import run.halo.app.core.extension.content.Comment;
|
||||
import run.halo.app.core.extension.content.Reply;
|
||||
import run.halo.app.event.post.ReplyEvent;
|
||||
import run.halo.app.extension.ExtensionClient;
|
||||
import run.halo.app.extension.ListOptions;
|
||||
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.index.query.Query;
|
||||
import run.halo.app.extension.router.selector.FieldSelector;
|
||||
|
||||
/**
|
||||
* Update the comment status after receiving the reply event.
|
||||
|
@ -54,35 +61,48 @@ public class ReplyEventReconciler implements Reconciler<ReplyEvent>, SmartLifecy
|
|||
// if the comment has been deleted, then do nothing.
|
||||
.filter(comment -> comment.getMetadata().getDeletionTimestamp() == null)
|
||||
.ifPresent(comment -> {
|
||||
|
||||
// order by reply creation time desc to get first as last reply time
|
||||
List<Reply> replies = client.list(Reply.class,
|
||||
record -> commentName.equals(record.getSpec().getCommentName())
|
||||
&& record.getMetadata().getDeletionTimestamp() == null,
|
||||
ReplyService.creationTimeAscComparator().reversed());
|
||||
var baseQuery = and(
|
||||
equal("spec.commentName", commentName),
|
||||
isNull("metadata.deletionTimestamp")
|
||||
);
|
||||
var pageRequest = PageRequestImpl.ofSize(1).withSort(
|
||||
Sort.by("spec.creationTime", "metadata.name").descending()
|
||||
);
|
||||
final Comment.CommentStatus status = comment.getStatusOrDefault();
|
||||
|
||||
Comment.CommentStatus status = comment.getStatusOrDefault();
|
||||
var replyPageResult =
|
||||
client.listBy(Reply.class, listOptionsWithFieldQuery(baseQuery), pageRequest);
|
||||
// total reply count
|
||||
status.setReplyCount(replies.size());
|
||||
status.setReplyCount((int) replyPageResult.getTotal());
|
||||
|
||||
long visibleReplyCount = replies.stream()
|
||||
.filter(reply -> isTrue(reply.getSpec().getApproved())
|
||||
&& isFalse(reply.getSpec().getHidden())
|
||||
)
|
||||
.count();
|
||||
status.setVisibleReplyCount((int) visibleReplyCount);
|
||||
|
||||
// calculate last reply time
|
||||
Instant lastReplyTime = replies.stream()
|
||||
// calculate last reply time from total replies(top 1)
|
||||
Instant lastReplyTime = replyPageResult.get()
|
||||
.map(reply -> reply.getSpec().getCreationTime())
|
||||
.findFirst()
|
||||
.map(reply -> defaultIfNull(reply.getSpec().getCreationTime(),
|
||||
reply.getMetadata().getCreationTimestamp())
|
||||
)
|
||||
.orElse(null);
|
||||
status.setLastReplyTime(lastReplyTime);
|
||||
|
||||
Instant lastReadTime = comment.getSpec().getLastReadTime();
|
||||
status.setUnreadReplyCount(Comment.getUnreadReplyCount(replies, lastReadTime));
|
||||
// calculate visible reply count(only approved and not hidden)
|
||||
var visibleReplyPageResult =
|
||||
client.listBy(Reply.class, listOptionsWithFieldQuery(and(
|
||||
baseQuery,
|
||||
equal("spec.approved", BooleanUtils.TRUE),
|
||||
equal("spec.hidden", BooleanUtils.FALSE)
|
||||
)), pageRequest);
|
||||
status.setVisibleReplyCount((int) visibleReplyPageResult.getTotal());
|
||||
|
||||
// calculate unread reply count(after last read time)
|
||||
var unReadQuery = Optional.ofNullable(comment.getSpec().getLastReadTime())
|
||||
.map(lastReadTime -> and(
|
||||
baseQuery,
|
||||
greaterThan("spec.creationTime", lastReadTime.toString())
|
||||
))
|
||||
.orElse(baseQuery);
|
||||
var unReadPageResult =
|
||||
client.listBy(Reply.class, listOptionsWithFieldQuery(unReadQuery), pageRequest);
|
||||
status.setUnreadReplyCount((int) unReadPageResult.getTotal());
|
||||
|
||||
status.setHasNewReply(defaultIfNull(status.getUnreadReplyCount(), 0) > 0);
|
||||
|
||||
client.update(comment);
|
||||
|
@ -90,6 +110,12 @@ public class ReplyEventReconciler implements Reconciler<ReplyEvent>, SmartLifecy
|
|||
return new Result(false, null);
|
||||
}
|
||||
|
||||
static ListOptions listOptionsWithFieldQuery(Query query) {
|
||||
var listOptions = new ListOptions();
|
||||
listOptions.setFieldSelector(FieldSelector.of(query));
|
||||
return listOptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Controller setupWith(ControllerBuilder builder) {
|
||||
return new DefaultController<>(
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package run.halo.app.theme.finders;
|
||||
|
||||
import java.util.Comparator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.core.extension.content.Reply;
|
||||
import run.halo.app.extension.ListResult;
|
||||
import run.halo.app.extension.PageRequest;
|
||||
import run.halo.app.extension.Ref;
|
||||
|
@ -26,6 +24,5 @@ public interface CommentPublicQueryService {
|
|||
Mono<ListResult<ReplyVo>> listReply(String commentName, @Nullable Integer page,
|
||||
@Nullable Integer size);
|
||||
|
||||
Mono<ListResult<ReplyVo>> listReply(String commentName, @Nullable Integer page,
|
||||
@Nullable Integer size, @Nullable Comparator<Reply> comparator);
|
||||
Mono<ListResult<ReplyVo>> listReply(String commentName, PageRequest pageRequest);
|
||||
}
|
||||
|
|
|
@ -4,17 +4,14 @@ package run.halo.app.theme.finders.impl;
|
|||
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 static run.halo.app.extension.index.query.QueryFactory.or;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
||||
|
@ -24,7 +21,6 @@ import org.springframework.util.Assert;
|
|||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import run.halo.app.content.comment.OwnerInfo;
|
||||
import run.halo.app.content.comment.ReplyService;
|
||||
import run.halo.app.core.extension.User;
|
||||
import run.halo.app.core.extension.content.Comment;
|
||||
import run.halo.app.core.extension.content.Reply;
|
||||
|
@ -36,7 +32,7 @@ import run.halo.app.extension.PageRequest;
|
|||
import run.halo.app.extension.PageRequestImpl;
|
||||
import run.halo.app.extension.ReactiveExtensionClient;
|
||||
import run.halo.app.extension.Ref;
|
||||
import run.halo.app.extension.index.query.QueryFactory;
|
||||
import run.halo.app.extension.index.query.Query;
|
||||
import run.halo.app.extension.router.selector.FieldSelector;
|
||||
import run.halo.app.infra.AnonymousUserConst;
|
||||
import run.halo.app.metrics.CounterService;
|
||||
|
@ -70,18 +66,19 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
|||
|
||||
@Override
|
||||
public Mono<ListResult<CommentVo>> list(Ref ref, Integer page, Integer size) {
|
||||
return list(ref, PageRequestImpl.of(pageNullSafe(page), sizeNullSafe(size), defaultSort()));
|
||||
return list(ref,
|
||||
PageRequestImpl.of(pageNullSafe(page), sizeNullSafe(size), defaultCommentSort()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ListResult<CommentVo>> list(Ref ref, PageRequest pageParam) {
|
||||
var pageRequest = Optional.ofNullable(pageParam)
|
||||
.map(page -> page.withSort(page.getSort().and(defaultSort())))
|
||||
.map(page -> page.withSort(page.getSort().and(defaultCommentSort())))
|
||||
.orElse(PageRequestImpl.ofSize(0));
|
||||
return fixedCommentFieldQuery(ref)
|
||||
.flatMap(fixedFieldQuery -> {
|
||||
return fixedCommentFieldSelector(ref)
|
||||
.flatMap(fieldSelector -> {
|
||||
var listOptions = new ListOptions();
|
||||
listOptions.setFieldSelector(fixedFieldQuery);
|
||||
listOptions.setFieldSelector(fieldSelector);
|
||||
return client.listBy(Comment.class, listOptions, pageRequest)
|
||||
.flatMap(listResult -> Flux.fromStream(listResult.get())
|
||||
.map(this::toCommentVo)
|
||||
|
@ -99,26 +96,29 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
|||
|
||||
@Override
|
||||
public Mono<ListResult<ReplyVo>> listReply(String commentName, Integer page, Integer size) {
|
||||
return listReply(commentName, page, size, ReplyService.creationTimeAscComparator());
|
||||
return listReply(commentName, PageRequestImpl.of(pageNullSafe(page), sizeNullSafe(size),
|
||||
defaultReplySort()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<ListResult<ReplyVo>> listReply(String commentName, Integer page, Integer size,
|
||||
Comparator<Reply> comparator) {
|
||||
return fixedReplyPredicate(commentName)
|
||||
.flatMap(fixedPredicate ->
|
||||
client.list(Reply.class, fixedPredicate,
|
||||
comparator,
|
||||
pageNullSafe(page), sizeNullSafe(size))
|
||||
public Mono<ListResult<ReplyVo>> listReply(String commentName, PageRequest pageParam) {
|
||||
return fixedReplyFieldSelector(commentName)
|
||||
.flatMap(fieldSelector -> {
|
||||
var listOptions = new ListOptions();
|
||||
listOptions.setFieldSelector(fieldSelector);
|
||||
var pageRequest = Optional.ofNullable(pageParam)
|
||||
.map(page -> page.withSort(page.getSort().and(defaultReplySort())))
|
||||
.orElse(PageRequestImpl.ofSize(0));
|
||||
return client.listBy(Reply.class, listOptions, pageRequest)
|
||||
.flatMap(list -> Flux.fromStream(list.get().map(this::toReplyVo))
|
||||
.concatMap(Function.identity())
|
||||
.collectList()
|
||||
.map(replyVos -> new ListResult<>(list.getPage(), list.getSize(),
|
||||
list.getTotal(),
|
||||
replyVos))
|
||||
)
|
||||
.defaultIfEmpty(new ListResult<>(page, size, 0L, List.of()))
|
||||
);
|
||||
);
|
||||
})
|
||||
.defaultIfEmpty(ListResult.emptyResult());
|
||||
}
|
||||
|
||||
Mono<CommentVo> toCommentVo(Comment comment) {
|
||||
|
@ -203,10 +203,10 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
|||
.map(OwnerInfo::from);
|
||||
}
|
||||
|
||||
private Mono<FieldSelector> fixedCommentFieldQuery(@Nullable Ref ref) {
|
||||
private Mono<FieldSelector> fixedCommentFieldSelector(@Nullable Ref ref) {
|
||||
return Mono.fromSupplier(
|
||||
() -> {
|
||||
var baseQuery = QueryFactory.isNull("metadata.deletionTimestamp");
|
||||
var baseQuery = isNull("metadata.deletionTimestamp");
|
||||
if (ref != null) {
|
||||
baseQuery =
|
||||
and(baseQuery,
|
||||
|
@ -214,43 +214,35 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
|||
}
|
||||
return baseQuery;
|
||||
})
|
||||
.flatMap(query -> {
|
||||
var approvedQuery = and(
|
||||
equal("spec.approved", BooleanUtils.TRUE),
|
||||
equal("spec.hidden", BooleanUtils.FALSE)
|
||||
);
|
||||
// we should list all comments that the user owns
|
||||
return getCurrentUserWithoutAnonymous()
|
||||
.map(username -> or(approvedQuery, equal("spec.owner",
|
||||
Comment.CommentOwner.ownerIdentity(User.KIND, username)))
|
||||
)
|
||||
.defaultIfEmpty(approvedQuery)
|
||||
.map(compositeQuery -> and(query, compositeQuery));
|
||||
})
|
||||
.flatMap(this::concatVisibleQuery)
|
||||
.map(FieldSelector::of);
|
||||
}
|
||||
|
||||
private Mono<Predicate<Reply>> fixedReplyPredicate(String commentName) {
|
||||
private Mono<Query> concatVisibleQuery(Query query) {
|
||||
Assert.notNull(query, "The query must not be null");
|
||||
var approvedQuery = and(
|
||||
equal("spec.approved", BooleanUtils.TRUE),
|
||||
equal("spec.hidden", BooleanUtils.FALSE)
|
||||
);
|
||||
// we should list all comments that the user owns
|
||||
return getCurrentUserWithoutAnonymous()
|
||||
.map(username -> or(approvedQuery, equal("spec.owner",
|
||||
Comment.CommentOwner.ownerIdentity(User.KIND, username)))
|
||||
)
|
||||
.defaultIfEmpty(approvedQuery)
|
||||
.map(compositeQuery -> and(query, compositeQuery));
|
||||
}
|
||||
|
||||
private Mono<FieldSelector> fixedReplyFieldSelector(String commentName) {
|
||||
Assert.notNull(commentName, "The commentName must not be null");
|
||||
// The comment name must be equal to the comment name of the reply
|
||||
Predicate<Reply> commentNamePredicate =
|
||||
reply -> reply.getSpec().getCommentName().equals(commentName)
|
||||
&& reply.getMetadata().getDeletionTimestamp() == null;
|
||||
|
||||
// is approved and not hidden
|
||||
Predicate<Reply> approvedPredicate =
|
||||
reply -> BooleanUtils.isFalse(reply.getSpec().getHidden())
|
||||
&& BooleanUtils.isTrue(reply.getSpec().getApproved());
|
||||
return getCurrentUserWithoutAnonymous()
|
||||
.map(username -> {
|
||||
Predicate<Reply> isOwner = reply -> {
|
||||
Comment.CommentOwner owner = reply.getSpec().getOwner();
|
||||
return owner != null && StringUtils.equals(username, owner.getName());
|
||||
};
|
||||
return approvedPredicate.or(isOwner);
|
||||
})
|
||||
.defaultIfEmpty(approvedPredicate)
|
||||
.map(commentNamePredicate::and);
|
||||
return Mono.fromSupplier(() -> and(
|
||||
equal("spec.commentName", commentName),
|
||||
isNull("metadata.deletionTimestamp")
|
||||
))
|
||||
.flatMap(this::concatVisibleQuery)
|
||||
.map(FieldSelector::of);
|
||||
}
|
||||
|
||||
Mono<String> getCurrentUserWithoutAnonymous() {
|
||||
|
@ -260,7 +252,7 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
|||
.filter(username -> !AnonymousUserConst.PRINCIPAL.equals(username));
|
||||
}
|
||||
|
||||
static Sort defaultSort() {
|
||||
static Sort defaultCommentSort() {
|
||||
return Sort.by(Sort.Order.desc("spec.top"),
|
||||
Sort.Order.asc("spec.priority"),
|
||||
Sort.Order.desc("spec.creationTime"),
|
||||
|
@ -268,6 +260,12 @@ public class CommentPublicQueryServiceImpl implements CommentPublicQueryService
|
|||
);
|
||||
}
|
||||
|
||||
static Sort defaultReplySort() {
|
||||
return Sort.by(Sort.Order.asc("spec.creationTime"),
|
||||
Sort.Order.asc("metadata.name")
|
||||
);
|
||||
}
|
||||
|
||||
int pageNullSafe(Integer page) {
|
||||
return defaultIfNull(page, 1);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package run.halo.app.theme.finders.impl;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
@ -19,15 +18,12 @@ import org.mockito.InjectMocks;
|
|||
import org.mockito.Mock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
import run.halo.app.core.extension.Counter;
|
||||
import run.halo.app.core.extension.User;
|
||||
import run.halo.app.core.extension.content.Comment;
|
||||
import run.halo.app.core.extension.content.Post;
|
||||
import run.halo.app.core.extension.content.Reply;
|
||||
import run.halo.app.core.extension.service.UserService;
|
||||
import run.halo.app.extension.GroupVersionKind;
|
||||
import run.halo.app.extension.ListResult;
|
||||
|
@ -214,190 +210,6 @@ class CommentPublicQueryServiceImplTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ListReplyTest {
|
||||
@Test
|
||||
void listWhenUserNotLogin() {
|
||||
// Mock
|
||||
mockWhenListRely();
|
||||
|
||||
commentPublicQueryService.listReply("fake-comment", 1, 10)
|
||||
.as(StepVerifier::create)
|
||||
.consumeNextWith(listResult -> {
|
||||
assertThat(listResult.getTotal()).isEqualTo(2);
|
||||
assertThat(listResult.getItems().size()).isEqualTo(2);
|
||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||
.isEqualTo("reply-approved");
|
||||
assertThat(listResult.getItems().get(0).getStats().getUpvote()).isEqualTo(9);
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = AnonymousUserConst.PRINCIPAL)
|
||||
void listWhenUserIsAnonymous() {
|
||||
// Mock
|
||||
mockWhenListRely();
|
||||
|
||||
commentPublicQueryService.listReply("fake-comment", 1, 10)
|
||||
.as(StepVerifier::create)
|
||||
.consumeNextWith(listResult -> {
|
||||
assertThat(listResult.getTotal()).isEqualTo(2);
|
||||
assertThat(listResult.getItems().size()).isEqualTo(2);
|
||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||
.isEqualTo("reply-approved");
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "fake-user")
|
||||
void listWhenUserLoggedIn() {
|
||||
mockWhenListRely();
|
||||
|
||||
commentPublicQueryService.listReply("fake-comment", 1, 10)
|
||||
.as(StepVerifier::create)
|
||||
.consumeNextWith(listResult -> {
|
||||
assertThat(listResult.getTotal()).isEqualTo(3);
|
||||
assertThat(listResult.getItems().size()).isEqualTo(3);
|
||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||
.isEqualTo("reply-not-approved");
|
||||
assertThat(listResult.getItems().get(1).getMetadata().getName())
|
||||
.isEqualTo("reply-approved");
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void desensitizeReply() throws JSONException {
|
||||
var reply = createReply();
|
||||
reply.getSpec().getOwner()
|
||||
.setAnnotations(new HashMap<>() {
|
||||
{
|
||||
put(Comment.CommentOwner.KIND_EMAIL, "mail@halo.run");
|
||||
}
|
||||
});
|
||||
reply.getSpec().setIpAddress("127.0.0.1");
|
||||
|
||||
Counter counter = new Counter();
|
||||
counter.setUpvote(0);
|
||||
when(counterService.getByName(any())).thenReturn(Mono.just(counter));
|
||||
|
||||
var result = commentPublicQueryService.toReplyVo(reply).block();
|
||||
result.getMetadata().setCreationTimestamp(null);
|
||||
result.getSpec().setCreationTime(null);
|
||||
JSONAssert.assertEquals("""
|
||||
{
|
||||
"metadata":{
|
||||
"name":"fake-reply"
|
||||
},
|
||||
"spec":{
|
||||
"raw":"fake-raw",
|
||||
"content":"fake-content",
|
||||
"owner":{
|
||||
"kind":"User",
|
||||
"name":"",
|
||||
"displayName":"fake-display-name",
|
||||
"annotations":{
|
||||
|
||||
}
|
||||
},
|
||||
"ipAddress":"",
|
||||
"hidden":false,
|
||||
"commentName":"fake-comment"
|
||||
},
|
||||
"owner":{
|
||||
"kind":"User",
|
||||
"displayName":"fake-display-name"
|
||||
},
|
||||
"stats":{
|
||||
"upvote":0
|
||||
}
|
||||
}
|
||||
""",
|
||||
JsonUtils.objectToJson(result),
|
||||
true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void mockWhenListRely() {
|
||||
// Mock
|
||||
Reply notApproved = createReply();
|
||||
notApproved.getMetadata().setName("reply-not-approved");
|
||||
notApproved.getSpec().setApproved(false);
|
||||
|
||||
Reply approved = createReply();
|
||||
approved.getMetadata().setName("reply-approved");
|
||||
approved.getSpec().setApproved(true);
|
||||
|
||||
Reply notApprovedWithAnonymous = createReply();
|
||||
notApprovedWithAnonymous.getMetadata().setName("reply-not-approved-anonymous");
|
||||
notApprovedWithAnonymous.getSpec().setApproved(false);
|
||||
notApprovedWithAnonymous.getSpec().getOwner().setName(AnonymousUserConst.PRINCIPAL);
|
||||
|
||||
Reply approvedButAnotherOwner = createReply();
|
||||
approvedButAnotherOwner.getMetadata()
|
||||
.setName("reply-approved-but-another-owner");
|
||||
approvedButAnotherOwner.getSpec().setApproved(true);
|
||||
approvedButAnotherOwner.getSpec().getOwner().setName("another");
|
||||
|
||||
Reply notApprovedAndAnotherOwner = createReply();
|
||||
notApprovedAndAnotherOwner.getMetadata()
|
||||
.setName("reply-not-approved-and-another");
|
||||
notApprovedAndAnotherOwner.getSpec().setApproved(false);
|
||||
notApprovedAndAnotherOwner.getSpec().getOwner().setName("another");
|
||||
|
||||
Reply notApprovedAndAnotherCommentName = createReply();
|
||||
notApprovedAndAnotherCommentName.getMetadata()
|
||||
.setName("reply-approved-and-another-comment-name");
|
||||
notApprovedAndAnotherCommentName.getSpec().setApproved(false);
|
||||
notApprovedAndAnotherCommentName.getSpec().setCommentName("another-fake-comment");
|
||||
|
||||
when(client.list(eq(Reply.class), any(),
|
||||
any(),
|
||||
eq(1),
|
||||
eq(10))
|
||||
).thenAnswer((Answer<Mono<ListResult<Reply>>>) invocation -> {
|
||||
Predicate<Reply> predicate =
|
||||
invocation.getArgument(1, Predicate.class);
|
||||
List<Reply> replies = Stream.of(
|
||||
notApproved,
|
||||
approved,
|
||||
approvedButAnotherOwner,
|
||||
notApprovedAndAnotherOwner,
|
||||
notApprovedWithAnonymous,
|
||||
notApprovedAndAnotherCommentName
|
||||
).filter(predicate).toList();
|
||||
return Mono.just(new ListResult<>(1, 10, replies.size(), replies));
|
||||
});
|
||||
|
||||
extractedUser();
|
||||
when(client.fetch(eq(User.class), any())).thenReturn(Mono.just(createUser()));
|
||||
|
||||
Counter counter = new Counter();
|
||||
counter.setUpvote(9);
|
||||
when(counterService.getByName(any())).thenReturn(Mono.just(counter));
|
||||
}
|
||||
|
||||
Reply createReply() {
|
||||
Reply reply = new Reply();
|
||||
reply.setMetadata(new Metadata());
|
||||
reply.getMetadata().setName("fake-reply");
|
||||
reply.setSpec(new Reply.ReplySpec());
|
||||
|
||||
reply.getSpec().setRaw("fake-raw");
|
||||
reply.getSpec().setContent("fake-content");
|
||||
reply.getSpec().setHidden(false);
|
||||
reply.getSpec().setCommentName("fake-comment");
|
||||
Comment.CommentOwner commentOwner = new Comment.CommentOwner();
|
||||
commentOwner.setKind(User.KIND);
|
||||
commentOwner.setName("fake-user");
|
||||
commentOwner.setDisplayName("fake-display-name");
|
||||
reply.getSpec().setOwner(commentOwner);
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
private void extractedUser() {
|
||||
User another = createUser();
|
||||
another.getMetadata().setName("another");
|
||||
|
|
|
@ -2,13 +2,18 @@ package run.halo.app.theme.finders.impl;
|
|||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
|
@ -19,6 +24,7 @@ import reactor.test.StepVerifier;
|
|||
import run.halo.app.core.extension.User;
|
||||
import run.halo.app.core.extension.content.Comment;
|
||||
import run.halo.app.core.extension.content.Post;
|
||||
import run.halo.app.core.extension.content.Reply;
|
||||
import run.halo.app.extension.Extension;
|
||||
import run.halo.app.extension.ExtensionStoreUtil;
|
||||
import run.halo.app.extension.GroupVersionKind;
|
||||
|
@ -223,7 +229,7 @@ class CommentPublicQueryServiceIntegrationTest {
|
|||
void sortTest() {
|
||||
var comments =
|
||||
client.listAll(Comment.class, new ListOptions(),
|
||||
CommentPublicQueryServiceImpl.defaultSort())
|
||||
CommentPublicQueryServiceImpl.defaultCommentSort())
|
||||
.collectList()
|
||||
.block();
|
||||
assertThat(comments).isNotNull();
|
||||
|
@ -279,6 +285,192 @@ class CommentPublicQueryServiceIntegrationTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ListReplyTest {
|
||||
private final List<Reply> storedReplies = mockRelies();
|
||||
@Autowired
|
||||
private CommentPublicQueryServiceImpl commentPublicQueryService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
Flux.fromIterable(storedReplies)
|
||||
.flatMap(reply -> client.create(reply))
|
||||
.as(StepVerifier::create)
|
||||
.expectNextCount(storedReplies.size())
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
Flux.fromIterable(storedReplies)
|
||||
.flatMap(CommentPublicQueryServiceIntegrationTest.this::deleteImmediately)
|
||||
.as(StepVerifier::create)
|
||||
.expectNextCount(storedReplies.size())
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void listWhenUserNotLogin() {
|
||||
commentPublicQueryService.listReply("fake-comment", 1, 10)
|
||||
.as(StepVerifier::create)
|
||||
.consumeNextWith(listResult -> {
|
||||
assertThat(listResult.getTotal()).isEqualTo(2);
|
||||
assertThat(listResult.getItems().size()).isEqualTo(2);
|
||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||
.isEqualTo("reply-approved");
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = AnonymousUserConst.PRINCIPAL)
|
||||
void listWhenUserIsAnonymous() {
|
||||
commentPublicQueryService.listReply("fake-comment", 1, 10)
|
||||
.as(StepVerifier::create)
|
||||
.consumeNextWith(listResult -> {
|
||||
assertThat(listResult.getTotal()).isEqualTo(2);
|
||||
assertThat(listResult.getItems().size()).isEqualTo(2);
|
||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||
.isEqualTo("reply-approved");
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(username = "fake-user")
|
||||
void listWhenUserLoggedIn() {
|
||||
commentPublicQueryService.listReply("fake-comment", 1, 10)
|
||||
.as(StepVerifier::create)
|
||||
.consumeNextWith(listResult -> {
|
||||
assertThat(listResult.getTotal()).isEqualTo(3);
|
||||
assertThat(listResult.getItems().size()).isEqualTo(3);
|
||||
assertThat(listResult.getItems().get(0).getMetadata().getName())
|
||||
.isEqualTo("reply-approved");
|
||||
assertThat(listResult.getItems().get(1).getMetadata().getName())
|
||||
.isEqualTo("reply-approved-but-another-owner");
|
||||
assertThat(listResult.getItems().get(2).getMetadata().getName())
|
||||
.isEqualTo("reply-not-approved");
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void desensitizeReply() throws JSONException {
|
||||
var reply = createReply();
|
||||
reply.getSpec().getOwner()
|
||||
.setAnnotations(new HashMap<>() {
|
||||
{
|
||||
put(Comment.CommentOwner.KIND_EMAIL, "mail@halo.run");
|
||||
}
|
||||
});
|
||||
reply.getSpec().setIpAddress("127.0.0.1");
|
||||
|
||||
var result = commentPublicQueryService.toReplyVo(reply).block();
|
||||
result.getMetadata().setCreationTimestamp(null);
|
||||
var jsonObject = JsonUtils.jsonToObject(fakeReplyJson(), JsonNode.class);
|
||||
((ObjectNode) jsonObject.get("owner"))
|
||||
.put("displayName", "已删除用户");
|
||||
JSONAssert.assertEquals(jsonObject.toString(),
|
||||
JsonUtils.objectToJson(result),
|
||||
true);
|
||||
}
|
||||
|
||||
String fakeReplyJson() {
|
||||
return """
|
||||
{
|
||||
"metadata":{
|
||||
"name":"fake-reply"
|
||||
},
|
||||
"spec":{
|
||||
"raw":"fake-raw",
|
||||
"content":"fake-content",
|
||||
"owner":{
|
||||
"kind":"User",
|
||||
"name":"",
|
||||
"displayName":"fake-display-name",
|
||||
"annotations":{
|
||||
|
||||
}
|
||||
},
|
||||
"creationTime": "2024-03-11T06:23:42.923294424Z",
|
||||
"ipAddress":"",
|
||||
"hidden": false,
|
||||
"allowNotification": false,
|
||||
"top": false,
|
||||
"priority": 0,
|
||||
"commentName":"fake-comment"
|
||||
},
|
||||
"owner":{
|
||||
"kind":"User",
|
||||
"displayName":"fake-display-name"
|
||||
},
|
||||
"stats":{
|
||||
"upvote":0
|
||||
}
|
||||
}
|
||||
""";
|
||||
}
|
||||
|
||||
private List<Reply> mockRelies() {
|
||||
// Mock
|
||||
Reply notApproved = createReply();
|
||||
notApproved.getMetadata().setName("reply-not-approved");
|
||||
notApproved.getSpec().setApproved(false);
|
||||
|
||||
Reply approved = createReply();
|
||||
approved.getMetadata().setName("reply-approved");
|
||||
approved.getSpec().setApproved(true);
|
||||
|
||||
Reply notApprovedWithAnonymous = createReply();
|
||||
notApprovedWithAnonymous.getMetadata().setName("reply-not-approved-anonymous");
|
||||
notApprovedWithAnonymous.getSpec().setApproved(false);
|
||||
notApprovedWithAnonymous.getSpec().getOwner().setName(AnonymousUserConst.PRINCIPAL);
|
||||
|
||||
Reply approvedButAnotherOwner = createReply();
|
||||
approvedButAnotherOwner.getMetadata()
|
||||
.setName("reply-approved-but-another-owner");
|
||||
approvedButAnotherOwner.getSpec().setApproved(true);
|
||||
approvedButAnotherOwner.getSpec().getOwner().setName("another");
|
||||
|
||||
Reply notApprovedAndAnotherOwner = createReply();
|
||||
notApprovedAndAnotherOwner.getMetadata()
|
||||
.setName("reply-not-approved-and-another");
|
||||
notApprovedAndAnotherOwner.getSpec().setApproved(false);
|
||||
notApprovedAndAnotherOwner.getSpec().getOwner().setName("another");
|
||||
|
||||
Reply notApprovedAndAnotherCommentName = createReply();
|
||||
notApprovedAndAnotherCommentName.getMetadata()
|
||||
.setName("reply-approved-and-another-comment-name");
|
||||
notApprovedAndAnotherCommentName.getSpec().setApproved(false);
|
||||
notApprovedAndAnotherCommentName.getSpec().setCommentName("another-fake-comment");
|
||||
|
||||
return List.of(
|
||||
notApproved,
|
||||
approved,
|
||||
approvedButAnotherOwner,
|
||||
notApprovedAndAnotherOwner,
|
||||
notApprovedWithAnonymous,
|
||||
notApprovedAndAnotherCommentName
|
||||
);
|
||||
}
|
||||
|
||||
Reply createReply() {
|
||||
var reply = JsonUtils.jsonToObject(fakeReplyJson(), Reply.class);
|
||||
reply.getMetadata().setName("fake-reply");
|
||||
|
||||
reply.getSpec().setRaw("fake-raw");
|
||||
reply.getSpec().setContent("fake-content");
|
||||
reply.getSpec().setHidden(false);
|
||||
reply.getSpec().setCommentName("fake-comment");
|
||||
Comment.CommentOwner commentOwner = new Comment.CommentOwner();
|
||||
commentOwner.setKind(User.KIND);
|
||||
commentOwner.setName("fake-user");
|
||||
commentOwner.setDisplayName("fake-display-name");
|
||||
reply.getSpec().setOwner(commentOwner);
|
||||
return reply;
|
||||
}
|
||||
}
|
||||
|
||||
Comment createComment() {
|
||||
return JsonUtils.jsonToObject("""
|
||||
{
|
||||
|
|
|
@ -186,7 +186,7 @@ export const ApiConsoleHaloRunV1alpha1CommentApiAxiosParamCreator = function (
|
|||
* @param {string} [ownerName] Commenter name.
|
||||
* @param {number} [page] The page number. Zero indicates no page.
|
||||
* @param {number} [size] Size of one page. Zero indicates no limit.
|
||||
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: creationTimestamp,replyCount,lastReplyTime
|
||||
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: metadata.creationTimestamp,status.replyCount,status.lastReplyTime
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
|
@ -342,7 +342,7 @@ export const ApiConsoleHaloRunV1alpha1CommentApiFp = function (
|
|||
* @param {string} [ownerName] Commenter name.
|
||||
* @param {number} [page] The page number. Zero indicates no page.
|
||||
* @param {number} [size] Size of one page. Zero indicates no limit.
|
||||
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: creationTimestamp,replyCount,lastReplyTime
|
||||
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: metadata.creationTimestamp,status.replyCount,status.lastReplyTime
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
|
@ -544,7 +544,7 @@ export interface ApiConsoleHaloRunV1alpha1CommentApiListCommentsRequest {
|
|||
readonly size?: number;
|
||||
|
||||
/**
|
||||
* Sort property and direction of the list result. Supported fields: creationTimestamp,replyCount,lastReplyTime
|
||||
* Sort property and direction of the list result. Supported fields: metadata.creationTimestamp,status.replyCount,status.lastReplyTime
|
||||
* @type {Array<string>}
|
||||
* @memberof ApiConsoleHaloRunV1alpha1CommentApiListComments
|
||||
*/
|
||||
|
|
|
@ -54,6 +54,7 @@ export const ApiConsoleHaloRunV1alpha1ReplyApiAxiosParamCreator = function (
|
|||
* @param {Array<string>} [labelSelector] Label selector for filtering.
|
||||
* @param {number} [page] The page number. Zero indicates no page.
|
||||
* @param {number} [size] Size of one page. Zero indicates no limit.
|
||||
* @param {Array<string>} [sort] Sort property and direction of the list result. Support sorting based on attribute name path.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
|
@ -63,6 +64,7 @@ export const ApiConsoleHaloRunV1alpha1ReplyApiAxiosParamCreator = function (
|
|||
labelSelector?: Array<string>,
|
||||
page?: number,
|
||||
size?: number,
|
||||
sort?: Array<string>,
|
||||
options: AxiosRequestConfig = {}
|
||||
): Promise<RequestArgs> => {
|
||||
const localVarPath = `/apis/api.console.halo.run/v1alpha1/replies`;
|
||||
|
@ -109,6 +111,10 @@ export const ApiConsoleHaloRunV1alpha1ReplyApiAxiosParamCreator = function (
|
|||
localVarQueryParameter["size"] = size;
|
||||
}
|
||||
|
||||
if (sort) {
|
||||
localVarQueryParameter["sort"] = Array.from(sort);
|
||||
}
|
||||
|
||||
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||
let headersFromBaseOptions =
|
||||
baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||
|
@ -143,6 +149,7 @@ export const ApiConsoleHaloRunV1alpha1ReplyApiFp = function (
|
|||
* @param {Array<string>} [labelSelector] Label selector for filtering.
|
||||
* @param {number} [page] The page number. Zero indicates no page.
|
||||
* @param {number} [size] Size of one page. Zero indicates no limit.
|
||||
* @param {Array<string>} [sort] Sort property and direction of the list result. Support sorting based on attribute name path.
|
||||
* @param {*} [options] Override http request option.
|
||||
* @throws {RequiredError}
|
||||
*/
|
||||
|
@ -152,6 +159,7 @@ export const ApiConsoleHaloRunV1alpha1ReplyApiFp = function (
|
|||
labelSelector?: Array<string>,
|
||||
page?: number,
|
||||
size?: number,
|
||||
sort?: Array<string>,
|
||||
options?: AxiosRequestConfig
|
||||
): Promise<
|
||||
(
|
||||
|
@ -165,6 +173,7 @@ export const ApiConsoleHaloRunV1alpha1ReplyApiFp = function (
|
|||
labelSelector,
|
||||
page,
|
||||
size,
|
||||
sort,
|
||||
options
|
||||
);
|
||||
return createRequestFunction(
|
||||
|
@ -205,6 +214,7 @@ export const ApiConsoleHaloRunV1alpha1ReplyApiFactory = function (
|
|||
requestParameters.labelSelector,
|
||||
requestParameters.page,
|
||||
requestParameters.size,
|
||||
requestParameters.sort,
|
||||
options
|
||||
)
|
||||
.then((request) => request(axios, basePath));
|
||||
|
@ -252,6 +262,13 @@ export interface ApiConsoleHaloRunV1alpha1ReplyApiListRepliesRequest {
|
|||
* @memberof ApiConsoleHaloRunV1alpha1ReplyApiListReplies
|
||||
*/
|
||||
readonly size?: number;
|
||||
|
||||
/**
|
||||
* Sort property and direction of the list result. Support sorting based on attribute name path.
|
||||
* @type {Array<string>}
|
||||
* @memberof ApiConsoleHaloRunV1alpha1ReplyApiListReplies
|
||||
*/
|
||||
readonly sort?: Array<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -279,6 +296,7 @@ export class ApiConsoleHaloRunV1alpha1ReplyApi extends BaseAPI {
|
|||
requestParameters.labelSelector,
|
||||
requestParameters.page,
|
||||
requestParameters.size,
|
||||
requestParameters.sort,
|
||||
options
|
||||
)
|
||||
.then((request) => request(this.axios, this.basePath));
|
||||
|
|
|
@ -79,6 +79,7 @@ export const PluginStatusLastProbeStateEnum = {
|
|||
Started: "STARTED",
|
||||
Stopped: "STOPPED",
|
||||
Failed: "FAILED",
|
||||
Unloaded: "UNLOADED",
|
||||
} as const;
|
||||
|
||||
export type PluginStatusLastProbeStateEnum =
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
* @interface TagStatus
|
||||
*/
|
||||
export interface TagStatus {
|
||||
/**
|
||||
*
|
||||
* @type {number}
|
||||
* @memberof TagStatus
|
||||
*/
|
||||
observedVersion?: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
|
|
Loading…
Reference in New Issue