Gradle-mcp gradle_mcp_concurrency_expert
install
source · Clone the upstream repo
git clone https://github.com/rnett/gradle-mcp
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/rnett/gradle-mcp "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.agents/skills/gradle_mcp_concurrency_expert" ~/.claude/skills/rnett-gradle-mcp-gradle-mcp-concurrency-expert && rm -rf "$T"
manifest:
.agents/skills/gradle_mcp_concurrency_expert/SKILL.mdsource content
Skill: Gradle MCP Concurrency Expert
This skill provides expert guidance on Kotlin Coroutines, Flow usage, and specialized locking mechanisms within the Gradle MCP project, including advanced patterns for testing asynchronous operations.
Coroutine & Flow Usage
- Parallel Source Processing: Source extraction and indexing are performed in parallel using Kotlin
andFlow
. This significantly improves performance but requires careful concurrency management (limiting global IO tasks).flatMapMerge - Parallelism Strategy: Prefer
(viaflatMapMerge
/parallelMap
utilities) for concurrency control over manualparallelForEach
management.Semaphore - Naming Conventions: Explicitly name non-deterministic parallelism utilities (e.g.,
) to signal that input order is not preserved.unorderedParallelMap - Flow Draining: Always ensure that indexing operations consume the entire file flow, even if the index is already up-to-date, when using a
based extraction pipeline to prevent deadlocks.Channel - Wait Policy: ALWAYS use
for suspending tests, NEVERrunTest
.runBlocking - Test Timeouts: Always specify a generous timeout (e.g., 10 minutes) for integration tests using
that trigger Gradle builds or start external processes. This prevents flaky failures due to the default 60-second timeout being exceeded during parallel execution or on slow machines.runTest
Locking & Re-entrancy
- Coroutine Re-entrancy: Use an immutable linked-list of held locks in
for thread-safe coroutine re-entrancy. This ensures child coroutines safely inherit held locks while maintaining strict isolation between parallel siblings.CoroutineContext.Element - Job Tracking: Ensure
is correctly tracked throughcurrentJob
calls, as everywithContext
creates a newwithContext
.Job - Lock Upgrades: Explicitly detect and fail Shared-to-Exclusive lock upgrade attempts. NIO
does not support upgrades within the same JVM process and will trigger anFileLock
.OverlappingFileLockException - Multi-Lock Avoidance: Avoid implementing utilities that acquire multiple file locks simultaneously (
) in a coroutine environment, especially within tests, to reduce deadlock risks.withLocks - Lock Release Polling: When using
in a polling loop to wait for another process to release a lock, ALWAYS close the acquired lock (e.g.,FileLockManager.tryLockAdvisory
) immediately. This prevents the waiting process from accidentally blocking other siblings by holding the lock it is trying to observe.lock?.close() - Context Parameters & Mockk: To mock functions with context parameters, use
for each parameter in theany<ContextParamType>()
block.context
Testing Asynchronous Events
- Deterministic Synchronization: Avoid
ordelay()
for synchronizing tests with background progress. Instead, useDispatchers.Unconfined
as a "signal" that can be completed by the tracker and awaited by the test.CompletableDeferred<Unit> - Lifecycle Management: Use
inbackgroundScope
when creating objects that launch long-lived background coroutines (likerunTest
).RunningBuild - Async Log Processing: When implementing asynchronous log processing using a
, always use aChannel
to signal completion of the processing loop.CompletableDeferred - Test Hooks: It is acceptable to add internal "onProgressFinished" or similar callback hooks to trackers specifically for test synchronization.
Examples
Testing a background progress tracker
- Create a
as a signal.CompletableDeferred<Unit> - In the tracker's
hook, complete the signal.onProgressFinished - In the test, await the signal before asserting the final state.
- Use
for the build process to ensure clean termination.backgroundScope
Mocking a function with context parameters
context(any<ProgressReporter>()) { myService.performTask(any()) }
Reasoning: Using
any() with explicit types in the context block to resolve overloads for Mockk.