chore(config): 移除 7 项从未被读取的死配置(5 个功能开关 + 2 个咨询附件桶)
产品裁定:确认移除对系统无影响即可移除。移除前的无影响论证(不是「看着没人用就删」):
全仓搜索 5 个 getter,命中的只有 ① 本类定义处 ② getAllFlags() ③ FeatureFlagControllerTest 一处断言
—— 业务代码零调用点;前端 admin-web/src 与 miniapp 对 feature-flag 零调用(仅一个未使用的 storageKey 常量)。
⚠️ 重要边界:FeatureFlagConfig **整体不能删** —— 同类的 isAppealEnabled(AppealService 4 处)、
isLocalEvidenceUploadEnabled(LocalEligibilityService)、getLocalEvidenceMaxFiles /
getLocalEvidenceMaxFileSizeMB / getLocalEvidenceAllowedTypes(PhotoService)都是**真实生效的 gate**。
本次只删那 5 个死的:counselingEnabled / premaritalEnabled / contentEnabled /
serviceLocationEnabled / localEligibilityEnabled,以及从未被读取的
counselingAttachmentsPrivate / counselingAttachmentsBucket(存储实走 object-storage.bucket-private)。
同步清理 application-docker.yml(application-dev.yml 被 .gitignore 排除,已在本地同步清理):
否则会留下「配了但不生效」的新死配置 —— 正是本次要消除的问题本身。
getAllFlags() 键数 21 → 14;FeatureFlagControllerTest 布尔样例由 counselingEnabled 换成 referralEnabled。
docs(plan): Task 3.1 全闭 + Task 3.2 前两项已完;附 B 增第 14 项;基线 685→689
Task 3.1(隐私设置)两层均已关闭:① upsert ② 桩接通 + 键集以小程序为准。
Task 3.2 第三项「PUT /feature-flags 不持久化」**仍未处理** —— 改动涉及运维流程
(改的是运行时内存态,重启即失效),与「删死配置」风险不同,需确认做成真持久化还是标注只读后关端点。
附 B-14:新增迁移必须同步更新 MigrationValidationTest.LATEST_MIGRATION(本轮实测踩到),
该守卫还断言「迁移文件总数 == 基线」即不允许缺号,属有效守卫。
全量回归 689 / 0 failures / 0 errors / 3 skipped;UI 契约门禁 18/18 绿。
This commit is contained in:
+8
-44
@@ -18,16 +18,12 @@ public class FeatureFlagConfig {
|
||||
private boolean appealEnabled = false;
|
||||
|
||||
// ---- V1.1 新增 Flag ----
|
||||
/** 公益婚恋咨询功能开关 */
|
||||
private boolean counselingEnabled = true;
|
||||
/** 婚前辅导功能开关(复用 counseling,默认跟随 counselingEnabled) */
|
||||
private boolean premaritalEnabled = true;
|
||||
/** 内容管理(婚恋课堂/反诈文章)开关 */
|
||||
private boolean contentEnabled = true;
|
||||
/** 善缘服务站功能开关 */
|
||||
private boolean serviceLocationEnabled = true;
|
||||
/** 本地资格核验功能开关 */
|
||||
private boolean localEligibilityEnabled = true;
|
||||
// ⚠️ 2026-09-19 移除:counselingEnabled / premaritalEnabled / contentEnabled /
|
||||
// serviceLocationEnabled / localEligibilityEnabled 五个开关**从未被任何业务代码读取**
|
||||
// (全仓搜索仅命中本类的定义与 getAllFlags,外加 FeatureFlagControllerTest 一处断言)。
|
||||
// 留着是「配置暴露但未强制」的假开关 —— 运维以为关掉能停功能,实际无效。
|
||||
// 若将来真需要按开关控制这些模块,应重新加入并**同时写入业务调用点**。
|
||||
//
|
||||
/** 红娘服务转介功能开关 */
|
||||
private boolean referralEnabled = true;
|
||||
/** 活动互选二阶段同意开关 */
|
||||
@@ -51,12 +47,8 @@ public class FeatureFlagConfig {
|
||||
/** 佐证材料保留天数;实际清理由运维任务按此配置执行 */
|
||||
private int localEvidenceRetentionDays = 365;
|
||||
|
||||
// ---- V1.1 咨询附件私存储 ----
|
||||
/** 咨询附件是否使用私有存储桶 */
|
||||
private boolean counselingAttachmentsPrivate = true;
|
||||
/** 咨询附件存储桶名称 */
|
||||
private String counselingAttachmentsBucket = "counseling-attachments";
|
||||
|
||||
// ⚠️ 2026-09-19 移除:counselingAttachmentsPrivate / counselingAttachmentsBucket 从未被读取 ——
|
||||
// 咨询附件的存储实走 object-storage.bucket-private,这两项与真实链路无关。
|
||||
// ==================== Getters & Setters ====================
|
||||
|
||||
public boolean isActivityEnabled() { return activityEnabled; }
|
||||
@@ -71,21 +63,6 @@ public class FeatureFlagConfig {
|
||||
public boolean isAppealEnabled() { return appealEnabled; }
|
||||
public void setAppealEnabled(boolean appealEnabled) { this.appealEnabled = appealEnabled; }
|
||||
|
||||
public boolean isCounselingEnabled() { return counselingEnabled; }
|
||||
public void setCounselingEnabled(boolean counselingEnabled) { this.counselingEnabled = counselingEnabled; }
|
||||
|
||||
public boolean isPremaritalEnabled() { return premaritalEnabled; }
|
||||
public void setPremaritalEnabled(boolean premaritalEnabled) { this.premaritalEnabled = premaritalEnabled; }
|
||||
|
||||
public boolean isContentEnabled() { return contentEnabled; }
|
||||
public void setContentEnabled(boolean contentEnabled) { this.contentEnabled = contentEnabled; }
|
||||
|
||||
public boolean isServiceLocationEnabled() { return serviceLocationEnabled; }
|
||||
public void setServiceLocationEnabled(boolean serviceLocationEnabled) { this.serviceLocationEnabled = serviceLocationEnabled; }
|
||||
|
||||
public boolean isLocalEligibilityEnabled() { return localEligibilityEnabled; }
|
||||
public void setLocalEligibilityEnabled(boolean localEligibilityEnabled) { this.localEligibilityEnabled = localEligibilityEnabled; }
|
||||
|
||||
public boolean isReferralEnabled() { return referralEnabled; }
|
||||
public void setReferralEnabled(boolean referralEnabled) { this.referralEnabled = referralEnabled; }
|
||||
|
||||
@@ -116,12 +93,6 @@ public class FeatureFlagConfig {
|
||||
public int getLocalEvidenceRetentionDays() { return localEvidenceRetentionDays; }
|
||||
public void setLocalEvidenceRetentionDays(int localEvidenceRetentionDays) { this.localEvidenceRetentionDays = localEvidenceRetentionDays; }
|
||||
|
||||
public boolean isCounselingAttachmentsPrivate() { return counselingAttachmentsPrivate; }
|
||||
public void setCounselingAttachmentsPrivate(boolean counselingAttachmentsPrivate) { this.counselingAttachmentsPrivate = counselingAttachmentsPrivate; }
|
||||
|
||||
public String getCounselingAttachmentsBucket() { return counselingAttachmentsBucket; }
|
||||
public void setCounselingAttachmentsBucket(String counselingAttachmentsBucket) { this.counselingAttachmentsBucket = counselingAttachmentsBucket; }
|
||||
|
||||
/**
|
||||
* 获取所有 Feature Flag 的当前值(供 /operator/feature-flags 接口使用)
|
||||
*/
|
||||
@@ -131,11 +102,6 @@ public class FeatureFlagConfig {
|
||||
flags.put("matchmakerEnabled", matchmakerEnabled);
|
||||
flags.put("chatImageEnabled", chatImageEnabled);
|
||||
flags.put("appealEnabled", appealEnabled);
|
||||
flags.put("counselingEnabled", counselingEnabled);
|
||||
flags.put("premaritalEnabled", premaritalEnabled);
|
||||
flags.put("contentEnabled", contentEnabled);
|
||||
flags.put("serviceLocationEnabled", serviceLocationEnabled);
|
||||
flags.put("localEligibilityEnabled", localEligibilityEnabled);
|
||||
flags.put("referralEnabled", referralEnabled);
|
||||
flags.put("mutualConsentEnabled", mutualConsentEnabled);
|
||||
flags.put("serviceProgramEnabled", serviceProgramEnabled);
|
||||
@@ -146,8 +112,6 @@ public class FeatureFlagConfig {
|
||||
flags.put("localEvidenceMaxFileSizeMB", localEvidenceMaxFileSizeMB);
|
||||
flags.put("localEvidenceAllowedTypes", localEvidenceAllowedTypes);
|
||||
flags.put("localEvidenceRetentionDays", localEvidenceRetentionDays);
|
||||
flags.put("counselingAttachmentsPrivate", counselingAttachmentsPrivate);
|
||||
flags.put("counselingAttachmentsBucket", counselingAttachmentsBucket);
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,11 +64,6 @@ features:
|
||||
chat-image-enabled: false
|
||||
appeal-enabled: false
|
||||
# V1.1
|
||||
counseling-enabled: true
|
||||
premarital-enabled: true
|
||||
content-enabled: true
|
||||
service-location-enabled: true
|
||||
local-eligibility-enabled: true
|
||||
referral-enabled: true
|
||||
mutual-consent-enabled: true
|
||||
service-program-enabled: true
|
||||
@@ -79,5 +74,3 @@ features:
|
||||
local-evidence-max-file-size-mb: 10
|
||||
local-evidence-allowed-types: ${LOCAL_EVIDENCE_ALLOWED_TYPES:jpg,png}
|
||||
local-evidence-retention-days: ${LOCAL_EVIDENCE_RETENTION_DAYS:365}
|
||||
counseling-attachments-private: true
|
||||
counseling-attachments-bucket: counseling-attachments
|
||||
|
||||
+17
-13
@@ -23,8 +23,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
* <p>背景(KEEP-VERIFY 复验发现):
|
||||
* <ul>
|
||||
* <li>D-22-A(High):原 {@code updateFlag} 仅支持布尔 flag(反射 {@code getMethod("set"+cap, boolean.class)}),
|
||||
* 7 个非布尔 flag(livenessProvider / localEvidenceAllowedTypes / counselingAttachmentsBucket /
|
||||
* localEvidenceMaxFiles / localEvidenceMaxFileSizeMB / localEvidenceRetentionDays)经 API 更新必失败。</li>
|
||||
* 非布尔 flag(livenessProvider / localEvidenceAllowedTypes / localEvidenceMaxFiles /
|
||||
* localEvidenceMaxFileSizeMB / localEvidenceRetentionDays)经 API 更新必失败。
|
||||
* (原文记 7 个,其中 counselingAttachmentsBucket / counselingAttachmentsPrivate
|
||||
* 已于 2026-09-19 作为**从未被读取的死配置**移除,故现为 5 个。)</li>
|
||||
* <li>D-22-B(Medium):原 {@code body.getOrDefault("value", false)} 缺 value 时静默置 false(可能误关功能),
|
||||
* 且非布尔类型转型会崩。</li>
|
||||
* </ul>
|
||||
@@ -56,15 +58,17 @@ class FeatureFlagControllerTest {
|
||||
ApiResponse<Map<String, Object>> resp = controller.getAllFlags();
|
||||
assertTrue(resp.isSuccess());
|
||||
Map<String, Object> flags = resp.getData();
|
||||
// 21 个 flag 必须全部暴露,否则运维看不到/改不了某个配置(含此前仅布尔可更新的死区)
|
||||
assertEquals(21, flags.size());
|
||||
// 14 个 flag 必须全部暴露,否则运维看不到/改不了某个配置(含此前仅布尔可更新的死区)。
|
||||
// 原为 21 个;2026-09-19 移除 7 个从未被业务代码读取的死配置
|
||||
// (counselingEnabled / premaritalEnabled / contentEnabled / serviceLocationEnabled /
|
||||
// localEligibilityEnabled / counselingAttachmentsPrivate / counselingAttachmentsBucket)。
|
||||
assertEquals(14, flags.size());
|
||||
for (String key : new String[]{
|
||||
"activityEnabled", "matchmakerEnabled", "chatImageEnabled", "appealEnabled",
|
||||
"counselingEnabled", "premaritalEnabled", "contentEnabled", "serviceLocationEnabled",
|
||||
"localEligibilityEnabled", "referralEnabled", "mutualConsentEnabled", "serviceProgramEnabled",
|
||||
"referralEnabled", "mutualConsentEnabled", "serviceProgramEnabled",
|
||||
"livenessEnabled", "livenessProvider", "localEvidenceUploadEnabled",
|
||||
"localEvidenceMaxFiles", "localEvidenceMaxFileSizeMB", "localEvidenceAllowedTypes",
|
||||
"localEvidenceRetentionDays", "counselingAttachmentsPrivate", "counselingAttachmentsBucket"
|
||||
"localEvidenceRetentionDays"
|
||||
}) {
|
||||
assertTrue(flags.containsKey(key), "缺少暴露的 flag: " + key);
|
||||
}
|
||||
@@ -72,10 +76,10 @@ class FeatureFlagControllerTest {
|
||||
|
||||
@Test
|
||||
void updateBooleanFlagIsReflected() {
|
||||
ApiResponse<Map<String, Object>> resp = controller.updateFlag(principal, "counselingEnabled", Map.of("value", false));
|
||||
ApiResponse<Map<String, Object>> resp = controller.updateFlag(principal, "referralEnabled", Map.of("value", false));
|
||||
assertTrue(resp.isSuccess());
|
||||
assertFalse(fixture.isCounselingEnabled());
|
||||
assertEquals(false, fixture.getAllFlags().get("counselingEnabled"));
|
||||
assertFalse(fixture.isReferralEnabled());
|
||||
assertEquals(false, fixture.getAllFlags().get("referralEnabled"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -100,14 +104,14 @@ class FeatureFlagControllerTest {
|
||||
|
||||
@Test
|
||||
void updateMissingValueReturnsBadRequest() {
|
||||
ApiResponse<Map<String, Object>> resp = controller.updateFlag(principal, "counselingEnabled", Map.of());
|
||||
ApiResponse<Map<String, Object>> resp = controller.updateFlag(principal, "referralEnabled", Map.of());
|
||||
assertFalse(resp.isSuccess());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateBooleanFlagWithWrongTypeReturnsBadRequestAndDoesNotSilentlyDisable() {
|
||||
ApiResponse<Map<String, Object>> resp = controller.updateFlag(principal, "counselingEnabled", Map.of("value", "not-a-bool"));
|
||||
ApiResponse<Map<String, Object>> resp = controller.updateFlag(principal, "referralEnabled", Map.of("value", "not-a-bool"));
|
||||
assertFalse(resp.isSuccess());
|
||||
assertTrue(fixture.isCounselingEnabled(), "类型不匹配不应静默把功能置为关闭");
|
||||
assertTrue(fixture.isReferralEnabled(), "类型不匹配不应静默把功能置为关闭");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user