refactor: optimize notification and subscription query using index (#5414)

### What type of PR is this?
/kind improvement
/area core
/milestone 2.13.x

### What this PR does / why we need it:
使用索引机制优化通知和订阅查询以提高性能

how to test it
测试通知列表不报错即可

### Does this PR introduce a user-facing change?

```release-note
使用索引机制优化通知和订阅查询以提高性能
```
pull/5422/head^2 v2.13.0-rc.1
guqing 2024-02-27 19:53:13 +08:00 committed by GitHub
parent d2f569699b
commit 11114416fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 242 additions and 300 deletions

View File

@ -0,0 +1,28 @@
package run.halo.app.core.extension.notification;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.Test;
/**
* Tests for {@link Subscription}.
*
* @author guqing
* @since 2.13.0
*/
class SubscriptionTest {
@Test
void reasonSubjectToStringTest() {
Subscription.ReasonSubject subject = new Subscription.ReasonSubject();
subject.setApiVersion("v1");
subject.setKind("Kind");
subject.setName("Name");
String expected = "Kind#v1/Name";
String actual = subject.toString();
assertThat(actual).isEqualTo(expected);
}
}

View File

@ -260,10 +260,58 @@ public class SchemeInitializer implements ApplicationListener<ApplicationContext
// notification.halo.run
schemeManager.register(ReasonType.class);
schemeManager.register(Reason.class);
schemeManager.register(NotificationTemplate.class);
schemeManager.register(Subscription.class);
schemeManager.register(NotificationTemplate.class, indexSpecs -> {
indexSpecs.add(new IndexSpec()
.setName("spec.reasonSelector.reasonType")
.setIndexFunc(simpleAttribute(NotificationTemplate.class,
template -> template.getSpec().getReasonSelector().getReasonType()))
);
});
schemeManager.register(Subscription.class, indexSpecs -> {
indexSpecs.add(new IndexSpec()
.setName("spec.reason.reasonType")
.setIndexFunc(simpleAttribute(Subscription.class,
subscription -> subscription.getSpec().getReason().getReasonType()))
);
indexSpecs.add(new IndexSpec()
.setName("spec.reason.subject")
.setIndexFunc(simpleAttribute(Subscription.class,
subscription -> subscription.getSpec().getReason().getSubject().toString()))
);
indexSpecs.add(new IndexSpec()
.setName("spec.subscriber")
.setIndexFunc(simpleAttribute(Subscription.class,
subscription -> subscription.getSpec().getSubscriber().toString()))
);
});
schemeManager.register(NotifierDescriptor.class);
schemeManager.register(Notification.class);
schemeManager.register(Notification.class, indexSpecs -> {
indexSpecs.add(new IndexSpec()
.setName("spec.unread")
.setIndexFunc(simpleAttribute(Notification.class,
notification -> String.valueOf(notification.getSpec().isUnread())))
);
indexSpecs.add(new IndexSpec()
.setName("spec.reason")
.setIndexFunc(simpleAttribute(Notification.class,
notification -> notification.getSpec().getReason()))
);
indexSpecs.add(new IndexSpec()
.setName("spec.recipient")
.setIndexFunc(simpleAttribute(Notification.class,
notification -> notification.getSpec().getRecipient()))
);
indexSpecs.add(new IndexSpec()
.setName("spec.title")
.setIndexFunc(simpleAttribute(Notification.class,
notification -> notification.getSpec().getTitle()))
);
indexSpecs.add(new IndexSpec()
.setName("spec.rawContent")
.setIndexFunc(simpleAttribute(Notification.class,
notification -> notification.getSpec().getRawContent()))
);
});
}
private static DefaultSchemeManager createSchemeManager(

View File

@ -1,6 +1,9 @@
package run.halo.app.notification;
import static org.apache.commons.lang3.StringUtils.defaultString;
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.or;
import java.util.HashMap;
import java.util.HashSet;
@ -12,7 +15,9 @@ import lombok.Builder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;
@ -23,8 +28,10 @@ import run.halo.app.core.extension.notification.Reason;
import run.halo.app.core.extension.notification.ReasonType;
import run.halo.app.core.extension.notification.Subscription;
import run.halo.app.extension.GroupVersionKind;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.Metadata;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.router.selector.FieldSelector;
import run.halo.app.notification.endpoint.SubscriptionRouter;
/**
@ -98,9 +105,11 @@ public class DefaultNotificationCenter implements NotificationCenter {
}
Flux<Subscription> listSubscription(Subscription.Subscriber subscriber) {
return client.list(Subscription.class,
subscription -> subscription.getSpec().getSubscriber().equals(subscriber),
null);
var listOptions = new ListOptions();
listOptions.setFieldSelector(FieldSelector.of(
equal("spec.subscriber", subscriber.toString()))
);
return client.listAll(Subscription.class, listOptions, defaultSort());
}
Flux<String> getNotifiersBySubscriber(Subscription.Subscriber subscriber, Reason reason) {
@ -310,31 +319,41 @@ public class DefaultNotificationCenter implements NotificationCenter {
Flux<Subscription> listObservers(String reasonTypeName,
Subscription.ReasonSubject reasonSubject) {
var distinctKeyPredicate = subscriptionDistinctKeyPredicate();
return client.list(Subscription.class,
subscription -> {
var interestReason = subscription.getSpec().getReason();
var sourceSubject = interestReason.getSubject();
if (StringUtils.isBlank(sourceSubject.getName())) {
return interestReason.getReasonType().equals(reasonTypeName)
&& sourceSubject.getApiVersion().equals(reasonSubject.getApiVersion())
&& sourceSubject.getKind().equals(reasonSubject.getKind());
Assert.notNull(reasonTypeName, "The reasonTypeName must not be null");
Assert.notNull(reasonSubject, "The reasonSubject must not be null");
final var listOptions = new ListOptions();
var matchAllSubject = new Subscription.ReasonSubject();
matchAllSubject.setKind(reasonSubject.getKind());
matchAllSubject.setApiVersion(reasonSubject.getApiVersion());
var fieldQuery = and(equal("spec.reason.reasonType", reasonTypeName),
or(equal("spec.reason.subject", reasonSubject.toString()),
// source reason subject name is blank present match all
equal("spec.reason.subject", matchAllSubject.toString())
)
);
listOptions.setFieldSelector(FieldSelector.of(fieldQuery));
return distinctByKey(client.listAll(Subscription.class, listOptions, defaultSort()));
}
static Flux<Subscription> distinctByKey(Flux<Subscription> source) {
final var distinctKeyPredicate = subscriptionDistinctKeyPredicate();
return source.distinct(Function.identity(), HashSet<Subscription>::new,
(set, val) -> {
for (Subscription subscription : set) {
if (distinctKeyPredicate.test(subscription, val)) {
return false;
}
return interestReason.getReasonType().equals(reasonTypeName)
&& interestReason.getSubject().equals(reasonSubject);
}, null)
.distinct(Function.identity(), HashSet<Subscription>::new,
(set, val) -> {
for (Subscription subscription : set) {
if (distinctKeyPredicate.test(subscription, val)) {
return false;
}
}
// no duplicated return true
set.add(val);
return true;
},
HashSet::clear);
}
// no duplicated return true
set.add(val);
return true;
},
HashSet::clear);
}
Sort defaultSort() {
return Sort.by(Sort.Order.asc("metadata.creationTimestamp"),
Sort.Order.asc("metadata.name"));
}
static BiPredicate<Subscription, Subscription> subscriptionDistinctKeyPredicate() {

View File

@ -26,10 +26,7 @@ public class DefaultNotificationService implements UserNotificationService {
@Override
public Mono<ListResult<Notification>> listByUser(String username, UserNotificationQuery query) {
var predicate = query.toPredicate()
.and(notification -> isRecipient(notification, username));
return client.list(Notification.class, predicate, query.toComparator(),
query.getPage(), query.getSize());
return client.listBy(Notification.class, query.toListOptions(), query.toPageRequest());
}
@Override

View File

@ -1,6 +1,7 @@
package run.halo.app.notification;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static run.halo.app.extension.index.query.QueryFactory.equal;
import java.util.Collections;
import java.util.Comparator;
@ -12,11 +13,14 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.notification.NotificationTemplate;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.router.selector.FieldSelector;
/**
* A default implementation of {@link ReasonNotificationTemplateSelector}.
@ -32,7 +36,11 @@ public class ReasonNotificationTemplateSelectorImpl implements ReasonNotificatio
@Override
public Mono<NotificationTemplate> select(String reasonType, Locale locale) {
return client.list(NotificationTemplate.class, matchReasonType(reasonType), null)
var listOptions = new ListOptions();
listOptions.setFieldSelector(FieldSelector.of(
equal("spec.reasonSelector.reasonType", reasonType))
);
return client.listAll(NotificationTemplate.class, listOptions, Sort.unsorted())
.collect(Collectors.groupingBy(
getLanguageKey(),
Collectors.maxBy(Comparator.comparing(t -> t.getMetadata().getCreationTimestamp()))

View File

@ -1,21 +1,23 @@
package run.halo.app.notification;
import static java.util.Comparator.comparing;
import static run.halo.app.extension.index.query.QueryFactory.and;
import static run.halo.app.extension.index.query.QueryFactory.contains;
import static run.halo.app.extension.index.query.QueryFactory.equal;
import static run.halo.app.extension.index.query.QueryFactory.or;
import static run.halo.app.extension.router.selector.SelectorUtil.labelAndFieldSelectorToListOptions;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Sort;
import org.springframework.lang.Nullable;
import org.springframework.web.server.ServerWebExchange;
import run.halo.app.core.extension.endpoint.SortResolver;
import run.halo.app.core.extension.notification.Notification;
import run.halo.app.extension.Comparators;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.PageRequest;
import run.halo.app.extension.PageRequestImpl;
import run.halo.app.extension.router.IListRequest;
import run.halo.app.extension.router.selector.FieldSelector;
/**
* Notification query object for authenticated user.
@ -27,9 +29,12 @@ public class UserNotificationQuery extends IListRequest.QueryListRequest {
private final ServerWebExchange exchange;
public UserNotificationQuery(ServerWebExchange exchange) {
private final String username;
public UserNotificationQuery(ServerWebExchange exchange, String username) {
super(exchange.getRequest().getQueryParams());
this.exchange = exchange;
this.username = username;
}
@Nullable
@ -37,79 +42,44 @@ public class UserNotificationQuery extends IListRequest.QueryListRequest {
return StringUtils.defaultIfBlank(queryParams.getFirst("keyword"), null);
}
@Nullable
@Schema(description = "true for unread, false for read, null for all")
public Boolean getUnRead() {
var unreadStr = queryParams.getFirst("unRead");
return StringUtils.isBlank(unreadStr) ? null : Boolean.parseBoolean(unreadStr);
}
@Nullable
@Schema(description = "Filter by notification reason")
public String getReason() {
return StringUtils.defaultIfBlank(queryParams.getFirst("reason"), null);
}
@ArraySchema(uniqueItems = true,
arraySchema = @Schema(name = "sort",
description = "Sort property and direction of the list result. Supported fields: "
+ "creationTimestamp"),
+ "metadata.creationTimestamp"),
schema = @Schema(description = "like field,asc or field,desc",
implementation = String.class,
example = "creationTimestamp,desc"))
public Sort getSort() {
return SortResolver.defaultInstance.resolve(exchange);
var sort = SortResolver.defaultInstance.resolve(exchange);
return sort.and(Sort.by(
Sort.Order.desc("metadata.creationTimestamp"),
Sort.Order.desc("metadata.name"))
);
}
/**
* Build a predicate from the query object.
*
* @return a predicate
* Build a list options from the query object.
*/
public Predicate<Notification> toPredicate() {
var unRead = getUnRead();
var reason = getReason();
Predicate<Notification> predicate = notification -> true;
if (unRead != null) {
predicate = predicate.and(notification
-> notification.getSpec().isUnread() == unRead);
public ListOptions toListOptions() {
var listOptions =
labelAndFieldSelectorToListOptions(getLabelSelector(), getFieldSelector());
var filedQuery = listOptions.getFieldSelector().query();
if (StringUtils.isNotBlank(getKeyword())) {
filedQuery = and(filedQuery,
or(
contains("spec.title", getKeyword()),
contains("spec.rawContent", getKeyword())
)
);
}
if (reason != null) {
predicate = predicate.and(notification
-> reason.equals(notification.getSpec().getReason()));
if (StringUtils.isNotBlank(username)) {
filedQuery = and(filedQuery, equal("spec.recipient", username));
}
if (getKeyword() != null) {
predicate = predicate.and(notification
-> notification.getSpec().getTitle().contains(getKeyword())
|| notification.getSpec().getHtmlContent().contains(getKeyword())
|| notification.getSpec().getRawContent().contains(getKeyword()));
}
return predicate;
listOptions.setFieldSelector(FieldSelector.of(filedQuery));
return listOptions;
}
/**
* Build a comparator from the query object.
*
* @return a comparator
*/
public Comparator<Notification> toComparator() {
var sort = getSort();
var creationTimestampOrder = sort.getOrderFor("creationTimestamp");
List<Comparator<Notification>> comparators = new ArrayList<>();
if (creationTimestampOrder != null) {
Comparator<Notification> comparator =
comparing(notification -> notification.getMetadata().getCreationTimestamp());
if (creationTimestampOrder.isDescending()) {
comparator = comparator.reversed();
}
comparators.add(comparator);
}
comparators.add(Comparators.defaultComparator());
return comparators.stream()
.reduce(Comparator::thenComparing)
.orElse(null);
public PageRequest toPageRequest() {
return PageRequestImpl.of(getPage(), getSize(), getSort());
}
}
}

View File

@ -143,8 +143,8 @@ public class UserNotificationEndpoint implements CustomEndpoint {
}
private Mono<ServerResponse> listNotification(ServerRequest request) {
var query = new UserNotificationQuery(request.exchange());
var username = request.pathVariable("username");
var query = new UserNotificationQuery(request.exchange(), username);
return notificationService.listByUser(username, query)
.flatMap(notifications -> ServerResponse.ok().bodyValue(notifications));
}

View File

@ -13,7 +13,6 @@ import static org.mockito.Mockito.when;
import java.util.List;
import java.util.Locale;
import java.util.function.Predicate;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@ -362,63 +361,8 @@ class DefaultNotificationCenterTest {
verify(notificationTemplateSelector).select(eq(reasonTypeName), any());
}
@Test
@SuppressWarnings("unchecked")
void listSubscriptionTest() {
var subscriptions = createSubscriptions();
when(client.list(eq(Subscription.class), any(Predicate.class), any()))
.thenAnswer(answer -> {
var predicate = (Predicate<Subscription>) answer.getArgument(1, Predicate.class);
return Flux.fromIterable(subscriptions)
.filter(predicate);
});
var subscription = subscriptions.get(0);
var subscriber = subscription.getSpec().getSubscriber();
notificationCenter.listSubscription(subscriber)
.as(StepVerifier::create)
.expectNext(subscription)
.verifyComplete();
verify(client).list(eq(Subscription.class), any(Predicate.class), any());
var otherSubscriber = JsonUtils.deepCopy(subscriber);
otherSubscriber.setName("other");
notificationCenter.listSubscription(otherSubscriber)
.as(StepVerifier::create)
.verifyComplete();
}
@Test
@SuppressWarnings("unchecked")
void listObserversTest() {
var subscriptions = createSubscriptions();
when(client.list(eq(Subscription.class), any(Predicate.class), any()))
.thenAnswer(answer -> {
var predicate = (Predicate<Subscription>) answer.getArgument(1, Predicate.class);
return Flux.fromIterable(subscriptions)
.filter(predicate);
});
var subscription = subscriptions.get(0);
var reasonTypeName = subscription.getSpec().getReason().getReasonType();
var reasonSubject = subscription.getSpec().getReason().getSubject();
notificationCenter.listObservers(reasonTypeName, reasonSubject)
.as(StepVerifier::create)
.expectNext(subscription)
.verifyComplete();
verify(client).list(eq(Subscription.class), any(Predicate.class), any());
notificationCenter.listObservers("other-reason", reasonSubject)
.as(StepVerifier::create)
.verifyComplete();
}
@Test
@SuppressWarnings("unchecked")
void listObserverWhenDuplicateSubscribers() {
var sourceSubscriptions = createSubscriptions();
var subscriptionA = sourceSubscriptions.get(0);
@ -427,26 +371,11 @@ class DefaultNotificationCenterTest {
var subscriptionC = JsonUtils.deepCopy(subscriptionA);
subscriptionC.getSpec().getReason().getSubject().setName(null);
var subscriptions = List.of(subscriptionA, subscriptionB, subscriptionC);
when(client.list(eq(Subscription.class), any(Predicate.class), any()))
.thenAnswer(answer -> {
var predicate = (Predicate<Subscription>) answer.getArgument(1, Predicate.class);
return Flux.fromIterable(subscriptions)
.filter(predicate);
});
var subscriptions = Flux.just(subscriptionA, subscriptionB, subscriptionC);
var subscription = subscriptions.get(0);
var reasonTypeName = subscription.getSpec().getReason().getReasonType();
var reasonSubject = subscription.getSpec().getReason().getSubject();
notificationCenter.listObservers(reasonTypeName, reasonSubject)
.as(StepVerifier::create)
.expectNext(subscription)
.verifyComplete();
verify(client).list(eq(Subscription.class), any(Predicate.class), any());
notificationCenter.listObservers("other-reason", reasonSubject)
DefaultNotificationCenter.distinctByKey(subscriptions)
.as(StepVerifier::create)
.expectNext(subscriptionA)
.verifyComplete();
}

View File

@ -17,6 +17,7 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.data.domain.Sort;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
import run.halo.app.core.extension.notification.NotificationTemplate;
@ -41,7 +42,7 @@ class ReasonNotificationTemplateSelectorImplTest {
@Test
void select() {
when(client.list(eq(NotificationTemplate.class), any(), any()))
when(client.listAll(eq(NotificationTemplate.class), any(), any(Sort.class)))
.thenReturn(Flux.fromIterable(templates()));
// language priority: zh_CN -> zh -> default
// if language is same, then compare creationTimestamp to get the latest one

View File

@ -28,7 +28,7 @@ const {
username: currentUser?.metadata.name as string,
page: 1,
size: 20,
unRead: true,
fieldSelector: ["spec.unread=true"],
});
return data.items;

View File

@ -229,6 +229,7 @@ models/reason-type-spec.ts
models/reason-type.ts
models/reason.ts
models/ref.ts
models/register-verify-email-request.ts
models/reply-list.ts
models/reply-request.ts
models/reply-spec.ts

View File

@ -36,7 +36,6 @@ import {
RequestArgs,
BaseAPI,
RequiredError,
operationServerMap,
} from "../base";
// @ts-ignore
import { PasswordResetEmailRequest } from "../models";
@ -48,7 +47,6 @@ import { ResetPasswordRequest } from "../models";
import { SignUpRequest } from "../models";
// @ts-ignore
import { User } from "../models";
/**
* ApiHaloRunV1alpha1UserApi - axios parameter creator
* @export
@ -338,18 +336,12 @@ export const ApiHaloRunV1alpha1UserApiFp = function (
resetPasswordRequest,
options
);
const index = configuration?.serverIndex ?? 0;
const operationBasePath =
operationServerMap["ApiHaloRunV1alpha1UserApi.resetPasswordByToken"]?.[
index
]?.url;
return (axios, basePath) =>
createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
)(axios, operationBasePath || basePath);
return createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
);
},
/**
* Send password reset email when forgot password
@ -368,18 +360,12 @@ export const ApiHaloRunV1alpha1UserApiFp = function (
passwordResetEmailRequest,
options
);
const index = configuration?.serverIndex ?? 0;
const operationBasePath =
operationServerMap[
"ApiHaloRunV1alpha1UserApi.sendPasswordResetEmail"
]?.[index]?.url;
return (axios, basePath) =>
createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
)(axios, operationBasePath || basePath);
return createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
);
},
/**
* Send registration verification email, which can be called when mustVerifyEmailOnRegistration in user settings is true
@ -398,18 +384,12 @@ export const ApiHaloRunV1alpha1UserApiFp = function (
registerVerifyEmailRequest,
options
);
const index = configuration?.serverIndex ?? 0;
const operationBasePath =
operationServerMap[
"ApiHaloRunV1alpha1UserApi.sendRegisterVerifyEmail"
]?.[index]?.url;
return (axios, basePath) =>
createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
)(axios, operationBasePath || basePath);
return createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
);
},
/**
* Sign up a new user
@ -427,16 +407,12 @@ export const ApiHaloRunV1alpha1UserApiFp = function (
signUpRequest,
options
);
const index = configuration?.serverIndex ?? 0;
const operationBasePath =
operationServerMap["ApiHaloRunV1alpha1UserApi.signUp"]?.[index]?.url;
return (axios, basePath) =>
createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
)(axios, operationBasePath || basePath);
return createRequestFunction(
localVarAxiosArgs,
globalAxios,
BASE_PATH,
configuration
);
},
};
};

View File

@ -176,10 +176,8 @@ export const ApiNotificationHaloRunV1alpha1NotificationApiAxiosParamCreator =
* @param {string} [keyword]
* @param {Array<string>} [labelSelector] Label selector for filtering.
* @param {number} [page] The page number. Zero indicates no page.
* @param {string} [reason] Filter by notification reason
* @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
* @param {boolean} [unRead] true for unread, false for read, null for all
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: metadata.creationTimestamp
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -189,10 +187,8 @@ export const ApiNotificationHaloRunV1alpha1NotificationApiAxiosParamCreator =
keyword?: string,
labelSelector?: Array<string>,
page?: number,
reason?: string,
size?: number,
sort?: Array<string>,
unRead?: boolean,
options: AxiosRequestConfig = {}
): Promise<RequestArgs> => {
// verify required parameter 'username' is not null or undefined
@ -241,10 +237,6 @@ export const ApiNotificationHaloRunV1alpha1NotificationApiAxiosParamCreator =
localVarQueryParameter["page"] = page;
}
if (reason !== undefined) {
localVarQueryParameter["reason"] = reason;
}
if (size !== undefined) {
localVarQueryParameter["size"] = size;
}
@ -253,10 +245,6 @@ export const ApiNotificationHaloRunV1alpha1NotificationApiAxiosParamCreator =
localVarQueryParameter["sort"] = Array.from(sort);
}
if (unRead !== undefined) {
localVarQueryParameter["unRead"] = unRead;
}
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions =
baseOptions && baseOptions.headers ? baseOptions.headers : {};
@ -540,10 +528,8 @@ export const ApiNotificationHaloRunV1alpha1NotificationApiFp = function (
* @param {string} [keyword]
* @param {Array<string>} [labelSelector] Label selector for filtering.
* @param {number} [page] The page number. Zero indicates no page.
* @param {string} [reason] Filter by notification reason
* @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
* @param {boolean} [unRead] true for unread, false for read, null for all
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: metadata.creationTimestamp
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
@ -553,10 +539,8 @@ export const ApiNotificationHaloRunV1alpha1NotificationApiFp = function (
keyword?: string,
labelSelector?: Array<string>,
page?: number,
reason?: string,
size?: number,
sort?: Array<string>,
unRead?: boolean,
options?: AxiosRequestConfig
): Promise<
(
@ -571,10 +555,8 @@ export const ApiNotificationHaloRunV1alpha1NotificationApiFp = function (
keyword,
labelSelector,
page,
reason,
size,
sort,
unRead,
options
);
return createRequestFunction(
@ -732,10 +714,8 @@ export const ApiNotificationHaloRunV1alpha1NotificationApiFactory = function (
requestParameters.keyword,
requestParameters.labelSelector,
requestParameters.page,
requestParameters.reason,
requestParameters.size,
requestParameters.sort,
requestParameters.unRead,
options
)
.then((request) => request(axios, basePath));
@ -873,13 +853,6 @@ export interface ApiNotificationHaloRunV1alpha1NotificationApiListUserNotificati
*/
readonly page?: number;
/**
* Filter by notification reason
* @type {string}
* @memberof ApiNotificationHaloRunV1alpha1NotificationApiListUserNotifications
*/
readonly reason?: string;
/**
* Size of one page. Zero indicates no limit.
* @type {number}
@ -888,18 +861,11 @@ export interface ApiNotificationHaloRunV1alpha1NotificationApiListUserNotificati
readonly size?: number;
/**
* Sort property and direction of the list result. Supported fields: creationTimestamp
* Sort property and direction of the list result. Supported fields: metadata.creationTimestamp
* @type {Array<string>}
* @memberof ApiNotificationHaloRunV1alpha1NotificationApiListUserNotifications
*/
readonly sort?: Array<string>;
/**
* true for unread, false for read, null for all
* @type {boolean}
* @memberof ApiNotificationHaloRunV1alpha1NotificationApiListUserNotifications
*/
readonly unRead?: boolean;
}
/**
@ -1026,10 +992,8 @@ export class ApiNotificationHaloRunV1alpha1NotificationApi extends BaseAPI {
requestParameters.keyword,
requestParameters.labelSelector,
requestParameters.page,
requestParameters.reason,
requestParameters.size,
requestParameters.sort,
requestParameters.unRead,
options
)
.then((request) => request(this.axios, this.basePath));

View File

@ -73,16 +73,3 @@ export class RequiredError extends Error {
this.name = "RequiredError";
}
}
interface ServerMap {
[key: string]: {
url: string,
description: string,
}[];
}
/**
*
* @export
*/
export const operationServerMap: ServerMap = {};

View File

@ -13,12 +13,19 @@
*/
export interface ConfigurationParameters {
apiKey?: string | Promise<string> | ((name: string) => string) | ((name: string) => Promise<string>);
apiKey?:
| string
| Promise<string>
| ((name: string) => string)
| ((name: string) => Promise<string>);
username?: string;
password?: string;
accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
accessToken?:
| string
| Promise<string>
| ((name?: string, scopes?: string[]) => string)
| ((name?: string, scopes?: string[]) => Promise<string>);
basePath?: string;
serverIndex?: number;
baseOptions?: any;
formDataCtor?: new () => any;
}
@ -29,7 +36,11 @@ export class Configuration {
* @param name security name
* @memberof Configuration
*/
apiKey?: string | Promise<string> | ((name: string) => string) | ((name: string) => Promise<string>);
apiKey?:
| string
| Promise<string>
| ((name: string) => string)
| ((name: string) => Promise<string>);
/**
* parameter for basic security
*
@ -50,7 +61,11 @@ export class Configuration {
* @param scopes oauth2 scope
* @memberof Configuration
*/
accessToken?: string | Promise<string> | ((name?: string, scopes?: string[]) => string) | ((name?: string, scopes?: string[]) => Promise<string>);
accessToken?:
| string
| Promise<string>
| ((name?: string, scopes?: string[]) => string)
| ((name?: string, scopes?: string[]) => Promise<string>);
/**
* override base path
*
@ -58,13 +73,6 @@ export class Configuration {
* @memberof Configuration
*/
basePath?: string;
/**
* override server index
*
* @type {number}
* @memberof Configuration
*/
serverIndex?: number;
/**
* base options for axios calls
*
@ -87,7 +95,6 @@ export class Configuration {
this.password = param.password;
this.accessToken = param.accessToken;
this.basePath = param.basePath;
this.serverIndex = param.serverIndex;
this.baseOptions = param.baseOptions;
this.formDataCtor = param.formDataCtor;
}
@ -103,7 +110,14 @@ export class Configuration {
* @return True if the given MIME is JSON, false otherwise.
*/
public isJsonMime(mime: string): boolean {
const jsonMime: RegExp = new RegExp("^(application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(;.*)?$", "i");
return mime !== null && (jsonMime.test(mime) || mime.toLowerCase() === "application/json-patch+json");
const jsonMime: RegExp = new RegExp(
"^(application/json|[^;/ \t]+/[^;/ \t]+[+]json)[ \t]*(;.*)?$",
"i"
);
return (
mime !== null &&
(jsonMime.test(mime) ||
mime.toLowerCase() === "application/json-patch+json")
);
}
}

View File

@ -24,10 +24,10 @@ import { User } from "./user";
export interface SignUpRequest {
/**
*
* @type {any}
* @type {string}
* @memberof SignUpRequest
*/
password: any;
password: string;
/**
*
* @type {User}
@ -36,8 +36,8 @@ export interface SignUpRequest {
user: User;
/**
*
* @type {any}
* @type {string}
* @memberof SignUpRequest
*/
verifyCode?: any;
verifyCode?: string;
}

View File

@ -31,7 +31,7 @@ const {
queryFn: async () => {
const { data } = await apiClient.notification.listUserNotifications({
username: currentUser?.metadata.name as string,
unRead: activeTab.value === "unread",
fieldSelector: [`spec.unread=${activeTab.value === "unread"}`],
});
return data;