Token导航 LogoToken导航

Agent Skill · 开发

atomic-matchmaking(原子牵线搭桥)

atomic-matchmaking 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

atomic-matchmaking 是开发类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在开发类的 21,746 个 Skill 里排第 16,013。

总安装 541周安装 23GitHub Stars 777下载 190核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:atomic-matchmaking(原子牵线搭桥)
来源仓库:https://github.com/dadbodgeoff/drift
仓库路径:skills/atomic-matchmaking
安装命令:
npx skills add https://github.com/dadbodgeoff/drift --skill atomic-matchmaking
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/dadbodgeoff/drift --skill atomic-matchmaking

这个 Skill 是做什么的

开发类 Skill 面向写代码、改代码和排查问题,一般会读写仓库文件,部分还会执行构建或测试命令。

atomic-matchmaking 实现双人匹配的两阶段提交机制,处理玩家断连与孤儿 lobby 问题。适用于实时多人游戏匹配系统,确保可靠通知与资源清理。分两阶段:健康检查(ping/pong)与 lobby 创建,任一失败则回滚。使用前应评估网络稳定性与超时阈值,避免误判正常连接。

适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

来源仓库内路径:skills/atomic-matchmaking

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/dadbodgeoff/drift --skill atomic-matchmaking;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

atomic-matchmaking 怎么安装?

在终端执行 npx skills add https://github.com/dadbodgeoff/drift --skill atomic-matchmaking。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

atomic-matchmaking 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

atomic-matchmaking 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

atomic-matchmaking 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

atomic-matchmaking 用的人多吗?

公开数据是累计安装 541 次,近一周安装 23 次,下载 190 次,GitHub 777 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

atomic-matchmaking 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理开发类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

开发类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
skill-vetter

技能审查员 · OpenClaw

8,779,018986操作浏览器MIT-0通过
ontology

本体论 · OpenClaw

6,636,960576只读MIT-0通过
entra-app-registration

内部应用程序注册 · Codex、Claude

6,631,872764接触敏感数据未明确通过
entra-app-registration

内部应用程序注册 · Codex、Claude

3,757,680201接触敏感数据未明确通过
nano-banana-pro

纳米香蕉专业版 · OpenClaw

3,526,898364接触敏感数据MIT-0有提醒
atomic-matchmaking

原子牵线搭桥 · 本页

541777需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Atomic Matchmaking with Two-Phase Commit

Two-phase commit semantics for match creation that handles player disconnections gracefully.

When to Use This Skill

  • Building real-time multiplayer matchmaking
  • Need to handle player disconnections during match creation
  • Want to avoid orphaned lobbies and stuck players
  • Require reliable match notifications

Core Concepts

Matching two players is deceptively hard. Either player can disconnect between being matched and joining. The solution uses two-phase commit:

  1. Phase 1: Verify both connections are healthy via ping/pong
  2. Phase 2: Create lobby, send notifications, confirm delivery
  3. Rollback: On any failure, clean up lobby and re-queue the healthy player

Implementation

Python

from dataclasses import dataclass, field
from datetime import datetime
from typing import Optional, Tuple
from enum import Enum
import asyncio

class MatchStatus(str, Enum):
    SUCCESS = "success"
    PLAYER1_DISCONNECTED = "player1_disconnected"
    PLAYER2_DISCONNECTED = "player2_disconnected"
    BOTH_DISCONNECTED = "both_disconnected"
    NOTIFICATION_FAILED = "notification_failed"

@dataclass
class MatchTicket:
    player_id: str
    category: str
    queued_at: datetime = field(default_factory=datetime.utcnow)

@dataclass
class MatchResult:
    status: MatchStatus
    lobby_id: Optional[str] = None
    lobby_code: Optional[str] = None
    player1_healthy: bool = True
    player2_healthy: bool = True
    requeued_player: Optional[str] = None

class ConnectionHealthChecker:
    """Verifies player connections are healthy before matching."""

    PING_TIMEOUT = 2.0
    MAX_ACCEPTABLE_LATENCY = 500  # ms

    def __init__(self, connection_manager):
        self._manager = connection_manager

    async def check_health(self, player_id: str) -> Tuple[bool, Optional[float]]:
        if not self._manager.is_user_connected(player_id):
            return False, None

        success, latency = await self._manager.ping_user(
            player_id, timeout=self.PING_TIMEOUT
        )

        if not success:
            return False, None

        if latency and latency > self.MAX_ACCEPTABLE_LATENCY:
            return False, latency

        return True, latency

    async def verify_both_healthy(
        self, player1_id: str, player2_id: str
    ) -> Tuple[bool, bool, bool]:
        results = await asyncio.gather(
            self.check_health(player1_id),
            self.check_health(player2_id),
        )

        health1, _ = results[0]
        health2, _ = results[1]

        return (health1 and health2), health1, health2

class AtomicMatchCreator:
    """Creates matches with two-phase commit semantics."""

    NOTIFICATION_TIMEOUT = 2.0
    NOTIFICATION_RETRIES = 3

    def __init__(
        self,
        health_checker: ConnectionHealthChecker,
        lobby_service,
        queue_manager,
        notification_service,
    ):
        self._health_checker = health_checker
        self._lobby_service = lobby_service
        self._queue_manager = queue_manager
        self._notifications = notification_service

    async def create_match(
        self, player1: MatchTicket, player2: MatchTicket
    ) -> MatchResult:
        # Phase 1: Health Check
        both_healthy, health1, health2 = await self._health_checker.verify_both_healthy(
            player1.player_id, player2.player_id
        )

        if not both_healthy:
            return await self._handle_health_failure(player1, player2, health1, health2)

        # Phase 2: Create Lobby & Notify
        lobby = None
        try:
            lobby = await self._lobby_service.create_lobby(
                host_id=player1.player_id,
                category=player1.category,
            )

            await self._lobby_service.add_player(lobby["id"], player2.player_id)

            # Notify both players in parallel
            notify_results = await asyncio.gather(
                self._notify_with_retry(player1.player_id, lobby["code"], player2.player_id),
                self._notify_with_retry(player2.player_id, lobby["code"], player1.player_id),
                return_exceptions=True,
            )

            if not all(r is True for r in notify_results):
                raise Exception("Notification failed")

            return MatchResult(
                status=MatchStatus.SUCCESS,
                lobby_id=lobby["id"],
                lobby_code=lobby["code"],
            )

        except Exception as e:
            # Rollback: delete lobby if created
            if lobby:
                await self._lobby_service.delete_lobby(lobby["id"])

            return await self._handle_phase2_failure(player1, player2, str(e))

    async def _handle_health_failure(
        self, player1: MatchTicket, player2: MatchTicket,
        health1: bool, health2: bool
    ) -> MatchResult:
        if not health1 and not health2:
            return MatchResult(
                status=MatchStatus.BOTH_DISCONNECTED,
                player1_healthy=False,
                player2_healthy=False,
            )

        # Re-queue the healthy player with priority
        if health1 and not health2:
            await self._queue_manager.requeue_player(player1, priority=True)
            return MatchResult(
                status=MatchStatus.PLAYER2_DISCONNECTED,
                player1_healthy=True,
                player2_healthy=False,
                requeued_player=player1.player_id,
            )

        if health2 and not health1:
            await self._queue_manager.requeue_player(player2, priority=True)
            return MatchResult(
                status=MatchStatus.PLAYER1_DISCONNECTED,
                player1_healthy=False,
                player2_healthy=True,
                requeued_player=player2.player_id,
            )

        return MatchResult(status=MatchStatus.BOTH_DISCONNECTED)

    async def _notify_with_retry(
        self, player_id: str, lobby_code: str, opponent_id: str
    ) -> bool:
        for attempt in range(self.NOTIFICATION_RETRIES):
            try:
                success = await asyncio.wait_for(
                    self._notifications.notify_match_found(player_id, lobby_code, opponent_id),
                    timeout=self.NOTIFICATION_TIMEOUT,
                )
                if success:
                    return True
            except asyncio.TimeoutError:
                pass

            if attempt < self.NOTIFICATION_RETRIES - 1:
                await asyncio.sleep(0.1)

        return False

Queue Manager with Priority Re-queue

from collections import deque
from typing import Dict, Optional, Set
import asyncio

class MatchmakingQueue:
    """FIFO queue with priority re-queue support."""

    def __init__(self):
        self._queues: Dict[str, deque] = {}
        self._player_tickets: Dict[str, MatchTicket] = {}
        self._lock = asyncio.Lock()

    async def enqueue(self, ticket: MatchTicket, priority: bool = False) -> bool:
        async with self._lock:
            if ticket.player_id in self._player_tickets:
                return False

            if ticket.category not in self._queues:
                self._queues[ticket.category] = deque()

            queue = self._queues[ticket.category]

            if priority:
                queue.appendleft(ticket)
            else:
                queue.append(ticket)

            self._player_tickets[ticket.player_id] = ticket
            return True

    async def dequeue_pair(self, category: str) -> Optional[tuple]:
        async with self._lock:
            queue = self._queues.get(category)
            if not queue or len(queue) < 2:
                return None

            ticket1 = queue.popleft()
            ticket2 = queue.popleft()

            self._player_tickets.pop(ticket1.player_id, None)
            self._player_tickets.pop(ticket2.player_id, None)

            return ticket1, ticket2

    async def requeue_player(self, ticket: MatchTicket, priority: bool = True) -> None:
        await self.remove_player(ticket.player_id)
        await self.enqueue(ticket, priority=priority)

Usage Examples

Match Creation Flow

health_checker = ConnectionHealthChecker(connection_manager)
match_creator = AtomicMatchCreator(
    health_checker, lobby_service, queue_manager, notification_service
)

# When two players are matched
result = await match_creator.create_match(ticket1, ticket2)

if result.status == MatchStatus.SUCCESS:
    print(f"Match created: {result.lobby_code}")
elif result.requeued_player:
    print(f"Re-queued {result.requeued_player}")

Best Practices

  1. Always verify connections before creating lobby - prevents orphaned lobbies
  2. Re-queue healthy players with priority - they've already waited
  3. Use notification retries - network can be flaky
  4. Rollback on any failure - clean up partial state
  5. Log correlation IDs - essential for debugging match failures

Common Mistakes

  • Creating lobby before verifying connections (orphaned lobbies)
  • Not re-queuing healthy players (stuck in limbo)
  • No notification retries (lost matches on network blips)
  • Missing rollback logic (resource leaks)
  • Not using priority re-queue (unfair to healthy players)

Related Patterns

  • websocket-management - Connection health verification
  • distributed-lock - Prevent race conditions in matching
  • graceful-shutdown - Drain queue on shutdown

平台分布

Codex

32.77%
按下载量换算62

Claude

30.21%
按下载量换算57

Cursor

20.25%
按下载量换算38

Gemini CLI

9.93%
按下载量换算19

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills