Skip to content

贡献指南

本指南涵盖了为 CoCache 贡献代码所需了解的一切:代码风格强制执行、测试要求、Pull Request 工作流以及如何添加新的缓存实现或模块。

代码风格

CoCache 通过 Detekt 强制执行代码风格,支持自动纠正。配置文件位于 config/detekt/detekt.yml,并应用于所有项目。

mermaid
graph LR
    subgraph CodeStyle["Code Style Enforcement"]
        direction TB
        EDIT["Write Code"] --> DETEKT["./gradlew detekt"]
        DETEKT --> PASS{"Pass?"}
        PASS -->|Yes| COMMIT["Commit"]
        PASS -->|No| FIX["./gradlew detektAutoFix"]
        FIX --> DETEKT
    end
    style CodeStyle fill:#161b22,stroke:#6d5dfc,color:#e6edf3
    style EDIT fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style DETEKT fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style PASS fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style FIX fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style COMMIT fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

Detekt 配置

项目覆盖了多条默认 Detekt 规则,以允许务实的编码模式。主要覆盖规则:

类别规则设置原因来源
complexityLongParameterList禁用缓存配置对象天然具有大量参数detekt.yml:3
complexityTooManyFunctions禁用缓存接口组合了多种操作类型detekt.yml:5
complexityNestedBlockDepth禁用缓存逻辑中深层嵌套是可以接受的detekt.yml:4
styleMaxLineLength300以容纳流式链式调用和注解detekt.yml:10
styleReturnCount禁用在缓存 get/set 逻辑中,多个提前返回可提高可读性detekt.yml:12
styleMagicNumber禁用TTL 值和缓存大小是领域特定的detekt.yml:18
styleUnusedPrivateMember禁用某些成员通过反射使用detekt.yml:15
styleWildcardImport允许 java.util.*常见的 Java 集合导入detekt.yml:21-24
namingMemberNameEqualsClassName禁用缓存接口方法天然与类名匹配detekt.yml:30
namingMatchingDeclarationName禁用测试和工具类灵活命名detekt.yml:31
exceptionsSwallowedException禁用缓存回退路径中的异常处理detekt.yml:34
performanceSpreadOperator禁用在 vararg API 中使用展开运算符detekt.yml:40
formattingNoWildcardImports允许 java.util.*,org.assertj.core.api.Assertions.*统一的导入风格detekt.yml:43-44

detekt-formatting 插件通过 cocache-dependencies 与核心 Detekt 插件一起应用,并且在项目级别启用了 autoCorrect = truebuild.gradle.kts:58)。

检查风格

bash
# 运行 Detekt 分析
./gradlew detekt

# 运行 Detekt 并自动格式化修正
./gradlew detektAutoFix

Detekt 作为 ./gradlew check 的一部分自动运行。提交前务必运行 detekt 以尽早发现问题。

测试要求

所有贡献必须包含适当的测试。CoCache 使用 JUnit 5 (Jupiter) 作为测试框架,mockk 用于模拟,fluent-assert 用于断言。

测试技术栈

工具用途版本来源
JUnit 5 Jupiter测试框架和参数化测试6.0.3libs.versions.toml:9
mockkKotlin 原生模拟框架1.14.9libs.versions.toml:11
fluent-assertKotlin 流式断言库(封装 AssertJ)0.2.6libs.versions.toml:10

断言风格

CoCache 要求所有测试断言使用 fluent-assert 库。禁止直接使用 AssertJ 的 assertThat()

kotlin
// 正确 -- fluent-assert 扩展
import me.ahoo.test.asserts.assert

cache[key].assert().isEqualTo(value)
result.assert().isNotNull()
count.assert().isOne()

// 错误 -- 不要直接使用 AssertJ
assertThat(cache[key]).isEqualTo(value)  // 不允许

fluent-assert 模式提供了 null 安全断言和更符合 Kotlin 习惯的语法。

TCK(技术兼容性套件)规范

cocache-test 模块提供了抽象规范类,定义了所有缓存实现的预期行为。新的实现必须继承这些规范。

mermaid
classDiagram
    class CacheSpec~K, V~ {
        <<abstract>>
        +createCache() Cache~K, V~
        +createCacheEntry() Pair~K, V~
        +get() void
        +set() void
        +setWithTtl() void
        +setWithTtlAmplitude() void
        +evict() void
        +setMissing() void
        +setMissingTtl() void
    }
    class ClientSideCacheSpec~V~ {
        <<abstract>>
        +createCache() ClientSideCache~V~
        +clear() void
    }
    class DistributedCacheSpec~V~ {
        <<abstract>>
        +createCache() DistributedCache~V~
    }
    class DefaultCoherentCacheSpec~K, V~ {
        <<abstract>>
        +createKeyConverter() KeyConverter~K~
        +createClientSideCache() ClientSideCache~V~
        +createDistributedCache() DistributedCache~V~
        +createCacheEvictedEventBus() CacheEvictedEventBus
        +getFromCacheSource() void
        +onEvicted() void
        +onEvictedWhenLoop() void
        +onEvictedWhenCacheNameNotMatch() void
    }
    class MultipleInstanceSyncSpec~K, V~ {
        <<abstract>>
        +createKeyConverter() KeyConverter~K~
        +createClientSideCache() ClientSideCache~V~
        +createDistributedCache() DistributedCache~V~
        +createCacheEvictedEventBus() CacheEvictedEventBus
        +multipleInstanceSync() void
    }
    class CacheEvictedEventBusSpec {
        <<abstract>>
        +createCacheEvictedEventBus() CacheEvictedEventBus
        +publish() void
        +register() void
    }

    CacheSpec <|-- ClientSideCacheSpec
    CacheSpec <|-- DistributedCacheSpec
    CacheSpec <|-- DefaultCoherentCacheSpec
    DefaultCoherentCacheSpec <|-- MultipleInstanceSyncSpec

    style CacheSpec fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style ClientSideCacheSpec fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style DistributedCacheSpec fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style DefaultCoherentCacheSpec fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style MultipleInstanceSyncSpec fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style CacheEvictedEventBusSpec fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
规范类测试内容工厂方法来源
CacheSpec<K, V>基本缓存操作(get、set、evict、TTL)createCache()createCacheEntry()cocache-test/.../CacheSpec.kt
ClientSideCacheSpec<V>L2 客户端缓存 + 清除操作createCache()(返回 ClientSideCache<V>cocache-test/.../ClientSideCacheSpec.kt
DistributedCacheSpec<V>L1 分布式缓存行为createCache()(返回 DistributedCache<V>cocache-test/.../DistributedCacheSpec.kt
DefaultCoherentCacheSpec<K, V>包含缓存源、驱逐事件、缓存击穿防护的完整一致性缓存createKeyConverter()createClientSideCache()createDistributedCache()createCacheEvictedEventBus()createCacheName()cocache-test/.../DefaultCoherentCacheSpec.kt
MultipleInstanceSyncSpec<K, V>通过事件总线实现跨实例缓存一致性DefaultCoherentCacheSpec 相同cocache-test/.../MultipleInstanceSyncSpec.kt
CacheEvictedEventBusSpec事件总线的发布和订阅行为createCacheEvictedEventBus()cocache-test/.../CacheEvictedEventBusSpec.kt

如何添加新的缓存实现

添加新的 ClientSideCacheDistributedCacheCacheEvictedEventBus 实现时,请遵循以下步骤:

mermaid
sequenceDiagram
autonumber
    participant Dev as Developer
    participant Impl as New Implementation
    participant TCK as TCK Spec
    participant Test as Test Class
    participant CI as CI Pipeline

    Dev->>Impl: Create implementation class
    Dev->>Test: Create test class extending TCK spec
    Dev->>Test: Implement factory methods
    Dev->>Test: Add implementation-specific tests
    Dev->>CI: ./gradlew :module:check
    CI->>TCK: Run inherited TCK tests
    CI->>Test: Run custom tests
    CI->>CI: Detekt analysis
    CI-->>Dev: All checks pass

第 1 步:实现接口

在相应的模块中创建你的实现。例如,一个新的 ClientSideCache

kotlin
// cocache-core/src/main/kotlin/me/ahoo/cache/client/MyClientSideCache.kt
class MyClientSideCache<V> : ClientSideCache<V> {
    // 实现所有接口方法
}

第 2 步:创建继承 TCK 规范的测试类

kotlin
// cocache-core/src/test/kotlin/me/ahoo/cache/client/MyClientSideCacheTest.kt
class MyClientSideCacheTest : ClientSideCacheSpec<String>() {
    override fun createCache(): ClientSideCache<String> {
        return MyClientSideCache()
    }

    override fun createCacheEntry(): Pair<String, String> {
        return "test-key" to "test-value"
    }

    // 在此添加针对具体实现的测试
}

第 3 步:运行测试

bash
./gradlew :cocache-core:test --tests "me.ahoo.cache.client.MyClientSideCacheTest"

继承的 TCK 测试会自动验证所有标准缓存行为。请添加自定义测试来覆盖具体实现的特性。

如何添加新模块

要添加一个全新的模块(例如新的分布式缓存后端):

mermaid
graph TD
    subgraph NewModule["Adding a New Module"]
        direction TB
        CREATE["1. Create module directory<br>and build.gradle.kts"] --> SETTINGS["2. Register in<br>settings.gradle.kts"]
        SETTINGS --> BUILD["3. Add dependencies<br>to build.gradle.kts"]
        BUILD --> IMPL["4. Implement interfaces"]
        IMPL --> TEST["5. Write tests extending TCK specs"]
        TEST --> ROOT["6. Update root build.gradle.kts<br>if needed"]
        ROOT --> VERIFY["7. ./gradlew :new-module:check"]
    end
    style NewModule fill:#161b22,stroke:#6d5dfc,color:#e6edf3
    style CREATE fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style SETTINGS fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style BUILD fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style IMPL fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style TEST fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style ROOT fill:#2d333b,stroke:#6d5dfc,color:#e6edf3
    style VERIFY fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

第 1 步:创建模块目录

cocache-my-backend/
  build.gradle.kts
  src/
    main/kotlin/me/ahoo/cache/mybackend/...
    test/kotlin/me/ahoo/cache/mybackend/...

第 2 步:在 settings.gradle.kts 中注册

将模块添加到 settings.gradle.kts

kotlin
include(":cocache-my-backend")

第 3 步:配置 build.gradle.kts

kotlin
// cocache-my-backend/build.gradle.kts
dependencies {
    api(project(":cocache-core"))
    // 或 api(project(":cocache-spring")) 用于 Spring 集成
    // 添加后端特定的依赖
    testImplementation(project(":cocache-test"))
}

该模块将自动继承以下配置:

  • JDK 17 工具链
  • Kotlin 编译器标志(-Xjsr305=strict-Xjvm-default=all-compatibility
  • Detekt 配置
  • JUnit 5 测试配置
  • 通用测试依赖(mockk、fluent-assert、logback)
  • Maven 发布配置

第 4 步:编写测试

继承 cocache-test 中相应的 TCK 规范,并添加针对具体实现的测试。

第 5 步:更新根构建脚本(如需要)

如果新模块应该包含在聚合覆盖率报告中,无需进行任何更改 -- code-coverage-report 会自动包含所有 libraryProjects

如果该模块是一个应用程序(如 cocache-example),请将其添加到根 build.gradle.ktsserverProjects 中:

kotlin
// [build.gradle.kts:34-36](https://github.com/Ahoo-Wang/CoCache/blob/main/build.gradle.kts#L34-L36)
val serverProjects = setOf(
    project(":cocache-example"),
    project(":cocache-my-backend"), // 如果是应用程序则添加在此
)

分支命名

遵循统一的分支命名规范:

模式用途示例
feature/<描述>新功能feature/redisson-distributed-cache
fix/<描述>Bug 修复fix/ttl-amplitude-calculation
refactor/<描述>代码重构refactor/extract-cache-source
docs/<描述>文档变更docs/update-api-reference
chore/<描述>构建、CI、依赖更新chore/upgrade-spring-boot

提交信息格式

使用约定式提交格式:

<type>(<scope>): <description>

[可选正文]
类型用途示例
feat新功能feat(core): add CaffeineCache implementation
fixBug 修复fix(spring-redis): handle null cache values
refactor代码重构refactor(api): extract CacheGetter interface
test添加或更新测试test(core): add concurrent access spec
docs文档docs(wiki): add publishing guide
chore构建、CI、依赖chore(deps): upgrade Kotlin to 2.3.20
ciCI/CD 变更ci: add CodeQL analysis workflow

Pull Request 工作流

mermaid
sequenceDiagram
autonumber
    participant Dev as Developer
    participant Branch as Feature Branch
    participant PR as Pull Request
    participant CI as CI Pipeline
    participant Review as Code Review
    participant Main as main

    Dev->>Branch: Create feature branch
    Dev->>Branch: Implement changes
    Dev->>Branch: ./gradlew check
    Dev->>PR: Open Pull Request
    PR->>CI: Trigger integration-test.yml
    CI->>CI: Run all test jobs (parallel)
    CI->>CI: Run codecov.yml
    CI-->>PR: Report status
    PR->>Review: Request review
    Review-->>PR: Approve / Request changes
    Dev->>PR: Address feedback (if any)
    PR->>Main: Merge to main

PR 检查清单

提交 Pull Request 之前,请确保:

  1. 所有测试通过./gradlew check 在本地成功运行
  2. Detekt 检查通过./gradlew detekt 通过(或先运行 detektAutoFix
  3. TCK 规范已继承:新实现继承了 cocache-test 中相应的规范类
  4. 覆盖率维持:新代码包含测试覆盖(Codecov 目标:60%)
  5. 无密钥提交:代码中没有凭据、令牌或特定环境的值
  6. API 兼容性:公共 API 变更保持向后兼容,或标记为破坏性变更并记录

相关页面

基于 Apache License 2.0 发布。