refactor(market): pom 坐标收口 market→member-api(facade 移入 member-api)+ tenant 依赖诚实化
承 bc-boundaries §三遗留(更深一层 BC 收口)。market-server pom 此前依赖 muse-module-member-server(可见 member 全部 internal),根因是 market 唯一引用的 member-server 类型 MarketAccountProjectionFacade(单方法读校验端口、无 DTO)。 - 接口 MarketAccountProjectionFacade 从 member-server application.account.facade 移到 member-api api.account(对称写端口 MuseAccountRecordProjectionApi:member 定义端口、 market 提供适配器 MarketAccountProjectionProvider、member-alone 回落 Unavailable*, 符合 bc-boundaries §一"本域定义端口、他域提供适配器") - market-server pom: muse-module-member-server → muse-module-member-api - market-server 直接声明 muse-spring-boot-starter-biz-tenant(此前经 member-server 传递, 收口暴露的隐性传递耦合 → 依赖诚实化) - 顺带修预存潜伏 test 编译破损:AppMuseMarketPublishControllerTest 的 9 参 PublishRecordItem 构造(record 自 commit a00c758 加 marketAssetId/appealStatus 变 10 参、 test 未同步;因 CI 从未在本特性分支运行而潜伏)→补 marketAssetId=null 验收:member-api/member-server/market-server scoped reactor test-compile BUILD SUCCESS; AccountMarketRecordServiceTest 8/0、MarketAccountProjectionFacadeConfigurationTest 3/0、 MarketAccountProjectionProviderTest 5/0、AppMuseMarketPublishControllerTest 10/0; BcBoundaryArchTest 1/0(0 Architecture Violation)。同步 bc-boundaries §三 + 台账 §一 TODO。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
053caf192f
commit
4e9923ce68
@ -42,7 +42,7 @@
|
||||
|
||||
> 豁免一律**临时、显式、可见**(测试源码点名)。违例消除后必须从 `KNOWN_VIOLATION_EXEMPTIONS` 删除该类——**收紧即整改验收**。新违例不在豁免内,一律红。
|
||||
|
||||
> 遗留(更深一层 BC 收口,不在本次范围):market-server 的 pom 仍依赖 `muse-module-member-server`(可见 member 全部 internal);本次只消除 member.dal 的**代码 import**(ArchUnit 校验 import、不校验 pom 坐标),pom 坐标收口可登记后续。
|
||||
> ✅ **pom 坐标收口已完成(2026-06-17)**:market-server pom 由 `muse-module-member-server`(可见 member 全部 internal)收窄为 `muse-module-member-api`。前置整改:market 唯一引用的 member-server 类型 `MarketAccountProjectionFacade`(单方法读校验端口、无 DTO)移到 member-api `api.account`——对称于写端口 `MuseAccountRecordProjectionApi`(member 定义端口、market 提供适配器 `MarketAccountProjectionProvider`、member-alone 回落 `UnavailableMarketAccountProjectionFacade`,符合 §一"本域定义端口、他域提供适配器");并把 market-server 此前**经 member-server 传递**获得的 `muse-spring-boot-starter-biz-tenant` 显式直接声明(依赖诚实化,收口暴露的隐性传递耦合)。验收:member-api/member-server/market-server scoped reactor `test-compile` BUILD SUCCESS;AccountMarketRecordServiceTest 8/0、MarketAccountProjectionFacadeConfigurationTest 3/0、MarketAccountProjectionProviderTest 5/0、AppMuseMarketPublishControllerTest 10/0;`BcBoundaryArchTest` 1/0(0 违例)。**顺带修**预存潜伏 test 编译破损:`AppMuseMarketPublishControllerTest` 的 9 参 `PublishRecordItem` 构造(record 自 commit a00c758 加 marketAssetId/appealStatus 变 10 参、该 test 未同步,因 CI 从未在本特性分支运行而潜伏)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
|
||||
**market 写路径整改(2026-06-14,ultracode)**:member 暴露写端口 `MuseAccountRecordProjectionApi` + DTO(member-server 实现读写自有 DAL、tenantId 由实现侧从上下文注入防伪造、事务沿用调用方),market 5 类改消费端口、移除 member.dal 依赖 → `KNOWN_VIOLATION_EXEMPTIONS` 清空、BC 门全绿。**附带修复**:round-2 重构 `ContentKnowledgeWorkOwnerFacade` 时遗留的旧测试 `KnowledgeWorkOwnerFacadeTest`(仍断言旧 WorkMapper 行为)已删除,其装配守卫/兜底两用例并入 `ContentKnowledgeWorkOwnerFacadeTest`(5/0F)——此为 round-2 一处假绿(当时构建在平台时区用例处中止、未真正跑到 knowledge),现已补正。
|
||||
|
||||
**后续基建 TODO**:openapi-diff CI 首跑验证(🔧 检测逻辑+循环聚合已本地实证 2026-06-17:oasdiff v1.19.1 对 7 域真实契约 5/5 拦真破坏/放行安全演化,镜像钉版本+复现脚本已落地;**仅余 GHA 触发管道待真实 PR 首跑**)、`completed=测试证据`兜底(台账加 testFiles 字段 + 门禁)、`dev-baseline` 收敛进 rules、跨域 `.application` 边界门、market-server→member-server pom 坐标收口(本次只消除 member.dal 代码 import,见 bc-boundaries §三遗留)、**ai/平台预存红测试整改**(CI 接电后将暴露;均非本轮改动引入):`MuseAiTaskServiceTest` 缺 `eventPublishOutboxService`/`candidateReviewService` 桩致 11 例 NPE **✅ 已整改 40/40(2026-06-15,补桩 + review lenient,零产代码改动)**;`QiniuSmsClientTest` 时区硬编码 **✅ 已整改 5/5(2026-06-15,断言改用与生产同款 `LocalDateTimeUtil.of` 由系统时区换算→机器无关)**;`MuseAiEventPublishOutboxMapperTest` **✅ 真实 PG 实跑 5/5(2026-06-15,mini-infra PG 100.64.0.8:5433;跑法=`source infra.env` + `-DargLine='-DsocksProxyHost= -DsocksProxyPort='`;隔离 schema 自建自清、零代码改动——原"红"仅缺真 PG 环境)**。**至此 ai/平台预存红三项全清。**
|
||||
**后续基建 TODO**:openapi-diff CI 首跑验证(🔧 检测逻辑+循环聚合已本地实证 2026-06-17:oasdiff v1.19.1 对 7 域真实契约 5/5 拦真破坏/放行安全演化,镜像钉版本+复现脚本已落地;**仅余 GHA 触发管道待真实 PR 首跑**)、`completed=测试证据`兜底(台账加 testFiles 字段 + 门禁)、`dev-baseline` 收敛进 rules、跨域 `.application` 边界门、market-server→member-server pom 坐标收口(✅ **已完成 2026-06-17**:接口 `MarketAccountProjectionFacade` 移入 member-api→market-server pom 收窄至 member-api + 直接声明 tenant starter[依赖诚实化];编译/4 测试 26 用例/BcBoundaryArchTest 0 违例全绿;顺带修预存潜伏 test 编译破损 AppMuseMarketPublishControllerTest;详见 bc-boundaries §三)、**ai/平台预存红测试整改**(CI 接电后将暴露;均非本轮改动引入):`MuseAiTaskServiceTest` 缺 `eventPublishOutboxService`/`candidateReviewService` 桩致 11 例 NPE **✅ 已整改 40/40(2026-06-15,补桩 + review lenient,零产代码改动)**;`QiniuSmsClientTest` 时区硬编码 **✅ 已整改 5/5(2026-06-15,断言改用与生产同款 `LocalDateTimeUtil.of` 由系统时区换算→机器无关)**;`MuseAiEventPublishOutboxMapperTest` **✅ 真实 PG 实跑 5/5(2026-06-15,mini-infra PG 100.64.0.8:5433;跑法=`source infra.env` + `-DargLine='-DsocksProxyHost= -DsocksProxyPort='`;隔离 schema 自建自清、零代码改动——原"红"仅缺真 PG 环境)**。**至此 ai/平台预存红三项全清。**
|
||||
|
||||
---
|
||||
|
||||
|
||||
@ -29,9 +29,15 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>muse-module-member-server</artifactId>
|
||||
<artifactId>muse-module-member-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<!-- market-server 直接使用 tenant 框架类型(TenantBaseDO/TenantContextHolder/TenantIgnore);
|
||||
此前经 member-server 传递获得,pom 收口去 member-server 后须显式直接声明(依赖诚实化)。 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>muse-spring-boot-starter-biz-tenant</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.cloud</groupId>
|
||||
<artifactId>muse-spring-boot-starter-security</artifactId>
|
||||
|
||||
@ -5,7 +5,7 @@ import cn.iocoder.muse.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.muse.module.market.dal.dataobject.muse.MuseMarketAccountProjectionDO;
|
||||
import cn.iocoder.muse.module.member.api.account.MuseAccountRecordProjectionApi;
|
||||
import cn.iocoder.muse.module.member.api.account.dto.MuseAccountRecordProjectionSaveReqDTO;
|
||||
import cn.iocoder.muse.module.member.application.account.facade.MarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.api.account.MarketAccountProjectionFacade;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
@ -17,7 +17,7 @@ import static cn.iocoder.muse.module.market.enums.ErrorCodeConstants.MARKET_ACCO
|
||||
/**
|
||||
* Market 提供给 member Account 的真实投影 provider。
|
||||
*
|
||||
* <p>该 Bean 实现 member 模块既有 {@link MarketAccountProjectionFacade}(该端口在 member-server, 非 .dal, 合规),
|
||||
* <p>该 Bean 实现 member 模块既有 {@link MarketAccountProjectionFacade}(该端口在 member-api, 非 .dal, 合规),
|
||||
* 用于替换默认 fail-closed unavailable facade,让读侧"投影已接入"判定不变。Account 查询仍只读 member 的
|
||||
* muse_account_record_projection。</p>
|
||||
*
|
||||
|
||||
@ -6,7 +6,7 @@ import cn.iocoder.muse.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.muse.module.market.dal.dataobject.muse.MuseMarketAccountProjectionDO;
|
||||
import cn.iocoder.muse.module.member.api.account.MuseAccountRecordProjectionApi;
|
||||
import cn.iocoder.muse.module.member.api.account.dto.MuseAccountRecordProjectionSaveReqDTO;
|
||||
import cn.iocoder.muse.module.member.application.account.facade.MarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.api.account.MarketAccountProjectionFacade;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
|
||||
@ -185,7 +185,7 @@ class AppMuseMarketPublishControllerTest extends BaseMockitoUnitTest {
|
||||
setLoginUser(9001L);
|
||||
when(publishService.listMyPublishRecords(9001L, "1", 1, 20, "work", "draft"))
|
||||
.thenReturn(new PageResult<>(List.of(new MarketPublishService.PublishRecordItem("8101",
|
||||
"可发布作品", "work", "2", "draft", "run_check", null, null, "publisher_only")), 1L));
|
||||
"可发布作品", "work", "2", "draft", "run_check", null, null, "publisher_only", null)), 1L));
|
||||
|
||||
mockMvc.perform(get("/muse/marketplace/my-publish-records")
|
||||
.header("X-API-Version", "1")
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.muse.module.member.api.account;
|
||||
|
||||
/**
|
||||
* Account 市场记录投影可用性边界(BC 对外 SPI 契约)。
|
||||
*
|
||||
* <p>Purchase / License / Publish records 在 Account 域只能读取
|
||||
* {@code muse_account_record_projection}。该 Facade 用来表达外部 Market 投影同步是否已经接入,
|
||||
* 防止 Account 在上游投影不可用时返回伪造的空数据。</p>
|
||||
*
|
||||
* <p>端口归属 member(读侧 fail-closed 判定, 由 member-server 的 {@code AccountMarketRecordServiceImpl} 消费);
|
||||
* 适配器由 Market owner 提供(market-server 的 {@code MarketAccountProjectionProvider} 实现),
|
||||
* member-alone(无 Market 接入)时回落 member-server 的 {@code UnavailableMarketAccountProjectionFacade}。
|
||||
* 置于 member-api 以便 market 在【不依赖 member-server internal】前提下提供适配器(对称于写端口
|
||||
* {@code MuseAccountRecordProjectionApi} 的布局, 使 market-server 的 pom 仅需依赖 member-api)。
|
||||
* 与【写】端口职责不同、刻意保持分离。</p>
|
||||
*/
|
||||
public interface MarketAccountProjectionFacade {
|
||||
|
||||
/**
|
||||
* 确认指定记录类型的 Market 投影已经可用。
|
||||
*
|
||||
* @param recordType Account 投影记录类型,只允许 service 内部传入固定值
|
||||
*/
|
||||
void requireProjectionAvailable(String recordType);
|
||||
}
|
||||
@ -17,8 +17,8 @@ import cn.iocoder.muse.module.member.api.account.dto.MuseAccountRecordProjection
|
||||
* (由 ArchUnit BcBoundaryArchTest 机械约束)。</p>
|
||||
*
|
||||
* <p>注:故意不把 member 既有【读校验】端口 {@code MarketAccountProjectionFacade.requireProjectionAvailable}
|
||||
* 合并进来 —— 那是 member 读侧 fail-closed 判定(member-server 内部用, 见 AccountMarketRecordServiceImpl),
|
||||
* 与本【写】端口职责不同, 保持分离。</p>
|
||||
* 合并进来 —— 那是 member 读侧 fail-closed 判定(同置本 member-api 包, 由 AccountMarketRecordServiceImpl 消费、
|
||||
* Market 适配器实现), 与本【写】端口职责不同, 保持分离。</p>
|
||||
*/
|
||||
public interface MuseAccountRecordProjectionApi {
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
package cn.iocoder.muse.autoconfigure.member.account;
|
||||
|
||||
import cn.iocoder.muse.module.member.application.account.facade.MarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.api.account.MarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.application.account.facade.UnavailableMarketAccountProjectionFacade;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
|
||||
@ -3,7 +3,7 @@ package cn.iocoder.muse.module.member.application.account;
|
||||
import cn.iocoder.muse.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.muse.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.muse.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.muse.module.member.application.account.facade.MarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.api.account.MarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.controller.account.vo.AccountPageResult;
|
||||
import cn.iocoder.muse.module.member.controller.admin.account.vo.AdminPurchaseRecordRespVO;
|
||||
import cn.iocoder.muse.module.member.controller.app.account.vo.AppLicenseRecordRespVO;
|
||||
|
||||
@ -1,18 +0,0 @@
|
||||
package cn.iocoder.muse.module.member.application.account.facade;
|
||||
|
||||
/**
|
||||
* Account 市场记录投影可用性边界。
|
||||
*
|
||||
* <p>Purchase / License / Publish records 在 Account 域只能读取
|
||||
* {@code muse_account_record_projection}。该 Facade 用来表达外部 Market 投影同步是否已经接入,
|
||||
* 防止 Account 在上游投影不可用时返回伪造的空数据。</p>
|
||||
*/
|
||||
public interface MarketAccountProjectionFacade {
|
||||
|
||||
/**
|
||||
* 确认指定记录类型的 Market 投影已经可用。
|
||||
*
|
||||
* @param recordType Account 投影记录类型,只允许 service 内部传入固定值
|
||||
*/
|
||||
void requireProjectionAvailable(String recordType);
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package cn.iocoder.muse.module.member.application.account.facade;
|
||||
|
||||
import cn.iocoder.muse.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.muse.module.member.api.account.MarketAccountProjectionFacade;
|
||||
|
||||
import static cn.iocoder.muse.module.member.enums.ErrorCodeConstants.ACCOUNT_MARKET_PROJECTION_UNAVAILABLE;
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@ import cn.iocoder.muse.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.muse.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.muse.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.muse.framework.test.core.ut.BaseMockitoUnitTest;
|
||||
import cn.iocoder.muse.module.member.application.account.facade.MarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.api.account.MarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.application.account.facade.UnavailableMarketAccountProjectionFacade;
|
||||
import cn.iocoder.muse.module.member.controller.account.vo.AccountPageResult;
|
||||
import cn.iocoder.muse.module.member.controller.admin.account.vo.AdminPurchaseRecordRespVO;
|
||||
|
||||
@ -2,6 +2,7 @@ package cn.iocoder.muse.module.member.application.account.facade;
|
||||
|
||||
import cn.iocoder.muse.autoconfigure.member.account.MarketAccountProjectionFacadeAutoConfiguration;
|
||||
import cn.iocoder.muse.framework.common.exception.ServiceException;
|
||||
import cn.iocoder.muse.module.member.api.account.MarketAccountProjectionFacade;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user