Skip to content

Commit

Permalink
refactor: subject sync pull and merge in SubjectSyncService (#712)
Browse files Browse the repository at this point in the history
* refactor: subject sync pull and merge in SubjectSyncService

* feat: add GetSubjectSyncsByPlatformAndPlatformId in SubjectSyncEndpoint

* docs: update CHANGELOG.MD
  • Loading branch information
chivehao authored Oct 19, 2024
1 parent 58f832e commit eb4c249
Show file tree
Hide file tree
Showing 21 changed files with 527 additions and 363 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

更新日志文档,版本顺序从新到旧,最新版本在最前(上)面。

# 0.18.0

> 注意:提供给插件的内部条目同步接口有所变化,此版本升级后,番组计划插件也需要升级到v18.x.x,不然无法正常快速拉取条目
- 重构条目三方同步逻辑
- 添加根据平台和平台ID查询条目ID

# 0.17.7

- 优化第三方同步在多线程下同步出现重复条目的情况
Expand Down
19 changes: 19 additions & 0 deletions api/src/main/java/run/ikaros/api/core/character/Character.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package run.ikaros.api.core.character;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Character {
private Long id;
private String name;
private String infobox;
private String summary;
}
19 changes: 19 additions & 0 deletions api/src/main/java/run/ikaros/api/core/person/Person.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package run.ikaros.api.core.person;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Person {
private Long id;
private String name;
private String infobox;
private String summary;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface SubjectOperate extends AllowPluginOperate {
Mono<Void> update(Subject subject);


Mono<Subject> syncByPlatform(@Nullable Long subjectId, SubjectSyncPlatform platform,
Mono<Void> syncByPlatform(@Nullable Long subjectId, SubjectSyncPlatform platform,
String platformId);


Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
package run.ikaros.api.core.subject;

import jakarta.annotation.Nullable;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.ikaros.api.core.subject.vo.PostSubjectSyncCondition;
import run.ikaros.api.plugin.AllowPluginOperate;
import run.ikaros.api.store.enums.SubjectSyncPlatform;

public interface SubjectSyncPlatformOperate extends AllowPluginOperate {
Mono<Subject> sync(@Nullable Long subjectId, SubjectSyncPlatform platform, String platformId);

Mono<Subject> sync(PostSubjectSyncCondition condition);
public interface SubjectSyncOperate extends AllowPluginOperate {
/**
* 从第三方平台同步条目,需要插件提供底层的数据获取支持.
*
* @param subjectId 可以为空,为空则是拉取创建新的,不为空则是先查询数据库,存在则更新,不存在则新增.
* @param platform 对应的平台
* @param platformId 对应的平台ID
*/
@Transactional
Mono<Void> sync(@Nullable Long subjectId, SubjectSyncPlatform platform, String platformId);

Mono<SubjectSync> save(SubjectSync subjectSync);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package run.ikaros.api.core.subject;

import java.util.List;
import org.pf4j.ExtensionPoint;
import reactor.core.publisher.Mono;
import run.ikaros.api.core.character.Character;
import run.ikaros.api.core.person.Person;
import run.ikaros.api.core.tag.Tag;
import run.ikaros.api.store.enums.SubjectSyncPlatform;

public interface SubjectSynchronizer extends ExtensionPoint {
Expand All @@ -13,31 +16,27 @@ public interface SubjectSynchronizer extends ExtensionPoint {
SubjectSyncPlatform getSyncPlatform();

/**
* 根据对应API从对应的平台拉取数据并转化成Ikaros的条目格式.
* 插件只需要组装数据即可.
*
* @param platformId 对应平台的条目Id.
* @return 从平台拉取的数据,进行格式转化。
* @see Subject
* 根据平台ID获取条目.
*/
Mono<Subject> pull(String platformId);
Subject fetchSubjectWithPlatformId(String platformId);

/**
* 根据对应API从对应平台拉取数据并合并到Ikaros已经存在的条目.
* 插件只需要组装数据即可.
*
* @param subject 已经存在的条目
* @param platformId 三方平台的条目ID
* @return 更新后的条目对象
* 根据平台ID获取剧集.
*/
Mono<Subject> merge(Subject subject, String platformId);
List<Episode> fetchEpisodesWithPlatformId(String platformId);

/**
* 同步对应平台ID条目及其所有的相关条目.
* 插件需要自己更新数据库相关表.
*
* @param platformId 平台ID
* @return 第一个(起点)条目
* 根据平台ID获取标签.
*/
List<Tag> fetchTagsWithPlatformId(String platformId);

/**
* 根据平台ID获取角色.
*/
List<Person> fetchPersonsWithPlatformId(String platformId);

/**
* 根据平台ID获取人物.
*/
Mono<Subject> pullSelfAndRelations(String platformId);
List<Character> fetchCharactersWithPlatformId(String platformId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@

import lombok.Builder;
import lombok.Data;
import run.ikaros.api.core.subject.SubjectSyncAction;
import org.springframework.lang.Nullable;
import run.ikaros.api.store.enums.SubjectSyncPlatform;

@Data
@Builder
public class PostSubjectSyncCondition {
/**
* 为空则是拉取创建新的,不为空则是先查询数据库,存在则更新,不存在则新增.
*/
@Nullable
private Long subjectId;
private SubjectSyncPlatform platform;
private String platformId;
private SubjectSyncAction subjectSyncAction;
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=0.17.7
version=0.18.0
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@
import run.ikaros.api.store.enums.SubjectSyncPlatform;
import run.ikaros.api.wrap.PagingWrap;
import run.ikaros.server.core.subject.service.SubjectService;
import run.ikaros.server.core.subject.service.SubjectSyncPlatformService;
import run.ikaros.server.core.subject.service.SubjectSyncService;

@Slf4j
@Component
public class SubjectOperator implements SubjectOperate {
private final SubjectService subjectService;
private final SubjectSyncPlatformService syncPlatformService;
private final SubjectSyncService syncPlatformService;

public SubjectOperator(SubjectService subjectService,
SubjectSyncPlatformService syncPlatformService) {
SubjectSyncService syncPlatformService) {
this.subjectService = subjectService;
this.syncPlatformService = syncPlatformService;
}
Expand Down Expand Up @@ -50,7 +50,7 @@ public Mono<Void> update(Subject subject) {
}

@Override
public Mono<Subject> syncByPlatform(@Nullable Long subjectId, SubjectSyncPlatform platform,
public Mono<Void> syncByPlatform(@Nullable Long subjectId, SubjectSyncPlatform platform,
String platformId) {
return syncPlatformService.sync(subjectId, platform, platformId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,25 @@
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.ikaros.api.core.subject.Subject;
import run.ikaros.api.core.subject.SubjectSync;
import run.ikaros.api.core.subject.SubjectSyncPlatformOperate;
import run.ikaros.api.core.subject.vo.PostSubjectSyncCondition;
import run.ikaros.api.core.subject.SubjectSyncOperate;
import run.ikaros.api.store.enums.SubjectSyncPlatform;
import run.ikaros.server.core.subject.service.SubjectSyncPlatformService;
import run.ikaros.server.core.subject.service.SubjectSyncService;

@Slf4j
@Component
public class SubjectSyncPlatformOperator implements SubjectSyncPlatformOperate {
private final SubjectSyncPlatformService service;
public class SubjectSyncOperator implements SubjectSyncOperate {
private final SubjectSyncService service;

public SubjectSyncPlatformOperator(SubjectSyncPlatformService service) {
public SubjectSyncOperator(SubjectSyncService service) {
this.service = service;
}

@Override
public Mono<Subject> sync(@Nullable Long subjectId, SubjectSyncPlatform platform,
String platformId) {
return service.sync(subjectId, platform, platformId);
}

@Override
public Mono<Subject> sync(PostSubjectSyncCondition condition) {
return service.sync(condition);
public Mono<Void> sync(@Nullable Long subjectId, SubjectSyncPlatform platform,
String platformId) {
return service.sync(subjectId, platform, platformId);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,24 @@
import run.ikaros.api.constant.OpenApiConst;
import run.ikaros.api.core.subject.Subject;
import run.ikaros.api.core.subject.SubjectSync;
import run.ikaros.api.core.subject.SubjectSyncAction;
import run.ikaros.api.core.subject.vo.PostSubjectSyncCondition;
import run.ikaros.api.infra.exception.subject.NoAvailableSubjectPlatformSynchronizerException;
import run.ikaros.api.store.enums.SubjectSyncPlatform;
import run.ikaros.server.core.subject.service.SubjectSyncPlatformService;
import run.ikaros.server.core.subject.service.SubjectSyncService;
import run.ikaros.server.endpoint.CoreEndpoint;

@Slf4j
@Component
public class SubjectSyncPlatformEndpoint implements CoreEndpoint {
private final SubjectSyncPlatformService service;
public class SubjectSyncEndpoint implements CoreEndpoint {
private final SubjectSyncService service;

public SubjectSyncPlatformEndpoint(SubjectSyncPlatformService service) {
public SubjectSyncEndpoint(SubjectSyncService service) {
this.service = service;
}


@Override
public RouterFunction<ServerResponse> endpoint() {
var tag = OpenApiConst.CORE_VERSION + "/subject/sync/platform";
var tag = OpenApiConst.CORE_VERSION + "/subject/sync";
return SpringdocRouteBuilder.route()
.POST("/subject/sync/platform", this::sync,
builder -> builder.operationId("SyncSubjectAndPlatform")
Expand All @@ -60,13 +58,6 @@ public RouterFunction<ServerResponse> endpoint() {
.description("Platform id")
.required(true)
.implementation(String.class))
.parameter(parameterBuilder()
.name("action")
.description("Sync action, such as PULL or MERGE, "
+ "default is PULL "
+ "PULL will override all subject meta info, "
+ "MERGE will update meta info that absent.")
.implementation(SubjectSyncAction.class))
.response(Builder.responseBuilder()
.implementation(Subject.class))
)
Expand All @@ -85,6 +76,25 @@ public RouterFunction<ServerResponse> endpoint() {
.implementationArray(SubjectSync.class))
)

.GET("/subject/syncs/platform", this::getSubjectSyncsByPlatformAndPlatformId,
builder -> builder.operationId("GetSubjectSyncsByPlatformAndPlatformId")
.tag(tag).description("Get subject syncs by subject id.")
.parameter(parameterBuilder()
.name("platform")
.description("Platform.")
.required(true)
.implementation(SubjectSyncPlatform.class))
.parameter(parameterBuilder()
.name("platformId")
.description("Platform id")
.in(ParameterIn.QUERY)
.required(true)
.implementation(Long.class))
.response(Builder.responseBuilder()
.description("Subject syncs by subject id.")
.implementationArray(SubjectSync.class))
)

.build();
}

Expand All @@ -103,16 +113,8 @@ private Mono<ServerResponse> sync(ServerRequest request) {
"'platformId' must has text.");
String platformId = platformIdOp.get();

Optional<String> actionOp = request.queryParam("action");
SubjectSyncAction subjectSyncAction =
SubjectSyncAction.valueOf(actionOp.orElse(SubjectSyncAction.PULL.name()));

PostSubjectSyncCondition condition = PostSubjectSyncCondition.builder()
.subjectId(subjectId).platform(platform)
.platformId(platformId).subjectSyncAction(subjectSyncAction)
.build();

return service.sync(condition)
return service.sync(subjectId, platform, platformId)
.flatMap(subject -> ServerResponse.ok().bodyValue(subject))
.onErrorResume(NoAvailableSubjectPlatformSynchronizerException.class,
err -> ServerResponse.status(HttpStatus.SERVICE_UNAVAILABLE)
Expand All @@ -129,4 +131,13 @@ private Mono<ServerResponse> findSubjectSyncsBySubjectId(ServerRequest request)
.collectList()
.flatMap(list -> ServerResponse.ok().bodyValue(list));
}

private Mono<ServerResponse> getSubjectSyncsByPlatformAndPlatformId(ServerRequest request) {
SubjectSyncPlatform platform = SubjectSyncPlatform.valueOf(
request.queryParam("platform").orElse(SubjectSyncPlatform.BGM_TV.name()));
Long platformId = Long.valueOf(request.queryParam("platformId").orElse("-1L"));
return service.findSubjectSyncsByPlatformAndPlatformId(platform, String.valueOf(platformId))
.collectList()
.flatMap(list -> ServerResponse.ok().bodyValue(list));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,20 @@
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.ikaros.api.core.subject.Subject;
import run.ikaros.api.core.subject.SubjectSync;
import run.ikaros.api.core.subject.vo.PostSubjectSyncCondition;
import run.ikaros.api.store.enums.SubjectSyncPlatform;

public interface SubjectSyncPlatformService {
Mono<Subject> sync(@Nullable Long subjectId, SubjectSyncPlatform platform, String platformId);

Mono<Subject> sync(PostSubjectSyncCondition condition);

public interface SubjectSyncService {
/**
* 同步对应平台ID条目及其所有的相关条目.
* 从第三方平台同步条目,需要插件提供底层的数据获取支持.
*
* @param platform 平台
* @param platformId 平台ID
* @return 第一个(起点)条目
* @param subjectId 可以为空,为空则是拉取创建新的,不为空则是先查询数据库,存在则更新,不存在则新增.
* @param platform 对应的平台
* @param platformId 对应的平台ID
*/
Mono<Subject> syncSelfAndRelations(SubjectSyncPlatform platform, String platformId);
@Transactional
Mono<Void> sync(@Nullable Long subjectId, SubjectSyncPlatform platform, String platformId);


@Transactional
Mono<SubjectSync> save(SubjectSync subjectSync);
Expand Down
Loading

0 comments on commit eb4c249

Please sign in to comment.