Skip to content

Instantly share code, notes, and snippets.

@wroyca
Last active February 6, 2026 16:19
Show Gist options
  • Select an option

  • Save wroyca/03f3c96215a8ae0023c6c15e7e7767d1 to your computer and use it in GitHub Desktop.

Select an option

Save wroyca/03f3c96215a8ae0023c6c15e7e7767d1 to your computer and use it in GitHub Desktop.

launcher -

launcher is a .

This file contains setup instructions and other details that are more appropriate for development rather than consumption. If you want to use launcher in your build2-based project, then instead see the accompanying package [README.md](/README.md) file.

The development setup for launcher uses the standard bdep-based workflow. For example:

git clone .../launcher.git
cd launcher

bdep init -C @gcc cc config.cxx=g++
bdep update
bdep test

Architecture

graph TB
    subgraph "Entry Point"
        main[main]
        opts[options parser]
    end

    subgraph "Controller Layer"
        ctrl[launcher_controller]
        ctx[runtime_context]
        rstate[remote_state]
    end

    subgraph "Coordinators"
        github[github_coordinator]
        http[http_coordinator]
        download[download_coordinator]
        progress[progress_coordinator]
        cache[cache_coordinator]
    end

    subgraph "Core Subsystems"
        reconciler[reconciler]
        db[(cache_database)]
        manifest[manifest_parser]
    end

    subgraph "Platform Layer"
        steam[steam_detector]
        proton[proton_manager]
    end

    main --> opts
    opts --> ctrl
    ctrl --> ctx
    ctrl --> rstate

    ctrl --> github
    ctrl --> http
    ctrl --> download
    ctrl --> progress
    ctrl --> cache

    cache --> reconciler
    cache --> db
    github --> manifest

    ctrl --> steam
    ctrl --> proton
Loading

Bootstrap Sequence

sequenceDiagram
    participant M as main()
    participant O as options
    participant S as Steam Detection
    participant U as Self-Update
    participant C as Controller
    participant G as GitHub API
    participant R as Reconciler
    participant D as Downloads
    participant P as Proton/Native

    M->>M: chdir(exe_directory)
    M->>O: parse(argc, argv)

    alt --wipe-settings
        M->>M: remove cache_root
    end

    alt path not specified
        M->>S: resolve_root()
        S-->>M: optional<path>
    end

    alt !no_self_update
        M->>U: check_self_update()
        U-->>M: restart?
    end

    M->>C: run()

    par Parallel Fetch
        C->>G: fetch_latest_release(client)
        C->>G: fetch_latest_release(rawfiles)
        C->>G: fetch_latest_release(helper)
        C->>G: fetch(dlc_manifest)
    end

    C->>R: plan(manifest)
    R-->>C: reconcile_items[]

    loop For each download
        C->>D: queue_download(item)
    end

    C->>D: execute_all()
    D-->>C: completion

    C->>R: verify pass
    C->>R: stamp(versions)

    C->>P: execute_payload()
    P-->>M: exit_code
Loading

Reconciliation Algorithm

flowchart TD
    A[Start Reconciliation] --> B{Version tags match?}
    B -->|Yes| C[Audit filesystem]
    B -->|No| D[Full manifest scan]

    C --> E{All files valid?}
    E -->|Yes| F[Return: up-to-date]
    E -->|No| D

    D --> G[For each manifest entry]
    G --> H{File in DB?}

    H -->|No| I[Action: DOWNLOAD]
    H -->|Yes| J{Check strategy}

    J -->|mtime| K{mtime matches?}
    J -->|mixed| L{mtime + size match?}
    J -->|hash| M{BLAKE3 matches?}

    K -->|Yes| N[Action: NONE]
    K -->|No| O[Action: DOWNLOAD]

    L -->|Yes| N
    L -->|No| O

    M -->|Yes| N
    M -->|No| O

    I --> P[Add to plan]
    O --> P
    N --> Q[Skip]

    P --> R{More entries?}
    Q --> R
    R -->|Yes| G
    R -->|No| S[Return plan]
Loading

Proton Integration (Linux)

sequenceDiagram
    participant L as Launcher
    participant P as proton_manager
    participant S as steam.exe (helper)
    participant G as Game

    L->>P: detect_proton_versions()
    P-->>L: proton_version[]

    L->>P: find_best_proton()
    P-->>L: Proton 9.0

    L->>P: build_environment(appid=10190)
    P-->>L: proton_environment

    L->>P: create_steam_appid()

    L->>P: run_ghost_process(steam.exe)
    Note over S: Initializes Steamworks API
    S-->>L: steam_running

    L->>P: launch_through_proton(iw4x.exe)
    P->>G: STEAM_COMPAT_DATA_PATH=... proton run iw4x.exe
Loading

File Synchronization Pipeline

flowchart LR
    subgraph Remote
        GH[GitHub Releases]
        CDN[CDN: cdn.iw4x.io]
    end

    subgraph Fetch
        API[github_api]
        HTTP[http_client]
    end

    subgraph Parse
        MAN[manifest_parser]
    end

    subgraph Reconcile
        REC[reconciler]
        DB[(SQLite)]
        FS[Filesystem]
    end

    subgraph Download
        DL[download_manager]
        PROG[progress_manager]
    end

    subgraph Extract
        ZIP[miniz]
    end

    GH --> API
    CDN --> HTTP
    API --> MAN
    HTTP --> MAN

    MAN --> REC
    DB <--> REC
    FS <--> REC

    REC -->|plan| DL
    DL --> PROG
    DL --> ZIP
    ZIP --> FS
    FS --> DB
Loading

Concurrency Model

flowchart TB
    subgraph "io_context (single-threaded)"
        direction TB
        EQ[Event Queue]
        EQ --> H1[HTTP handler]
        EQ --> H2[Timer handler]
        EQ --> H3[Download handler]
    end

    subgraph "Coroutines"
        C1[fetch_release]
        C2[download_file]
        C3[verify_hash]
    end

    C1 -.->|co_await| EQ
    C2 -.->|co_await| EQ
    C3 -.->|co_await| EQ

    subgraph "parallel_group"
        PG[make_parallel_group]
        PG --> C1
        PG --> C2
    end
Loading

Download Task State Machine

stateDiagram-v2
    [*] --> pending: Task created

    pending --> downloading: execute()
    pending --> cancelled: cancel_requested

    downloading --> completed: Success
    downloading --> failed: Error/Timeout
    downloading --> cancelled: cancel_requested
    downloading --> paused: pause_requested

    paused --> downloading: resume()
    paused --> cancelled: cancel_requested

    completed --> [*]
    failed --> pending: retry()
    cancelled --> [*]
Loading

Download Manager Flow

flowchart TB
    subgraph "Queue Phase"
        REQ[download_request]
        TASK[basic_download_task]
        QUEUE[(task queue)]
    end

    subgraph "Execution Phase"
        SCHED[Scheduler]
        ACTIVE[Active Tasks]
        POOL[Connection Pool]
    end

    subgraph "Completion Phase"
        CB[on_progress callback]
        STATE[state_callback]
        DONE[batch_completion]
    end

    REQ --> |add_task| TASK
    TASK --> QUEUE

    QUEUE --> |execute_all| SCHED
    SCHED --> |max_parallel| ACTIVE
    ACTIVE --> POOL

    POOL --> |bytes| CB
    POOL --> |state change| STATE
    ACTIVE --> |all done| DONE
Loading

Self-Update Sequence

sequenceDiagram
    participant U as update_coordinator
    participant D as update_discovery
    participant I as update_installer
    participant G as GitHub API
    participant FS as Filesystem

    U->>D: check_for_update(owner, repo, version)
    D->>G: fetch_latest_release()
    G-->>D: release_info

    alt Version matches
        D-->>U: empty (up-to-date)
    else New version available
        D-->>U: update_info{version, asset_url}
        U->>I: install_update(info)

        I->>G: download_asset(url)
        G-->>I: binary_data

        I->>FS: write_temp_file()
        I->>FS: atomic_replace(executable)

        I-->>U: update_result{success}
        U->>U: restart()
    end
Loading

Progress Rendering Pipeline

flowchart LR
    subgraph "Data Layer (Lock-Free)"
        METRICS[progress_metrics]
        TRACKER[progress_tracker]
    end

    subgraph "Manager Layer"
        ENTRY[progress_entry]
        MANAGER[progress_manager]
    end

    subgraph "Render Layer"
        SNAP[progress_snapshot]
        CTX[render_context]
        RENDER[progress_renderer]
        TTY[Terminal Output]
    end

    METRICS --> |atomic read| SNAP
    TRACKER --> |speed calc| SNAP

    ENTRY --> |owns| METRICS
    ENTRY --> |owns| TRACKER
    MANAGER --> |manages| ENTRY

    SNAP --> CTX
    CTX --> RENDER
    RENDER --> TTY
Loading

Progress Manager Lifecycle

stateDiagram-v2
    [*] --> Stopped: Constructor

    Stopped --> Running: start()
    Running --> Stopped: stop()

    state Running {
        [*] --> UpdateLoop
        UpdateLoop --> RenderLoop: parallel

        state UpdateLoop {
            [*] --> WaitUpdate
            WaitUpdate --> CollectSnapshots: timer expires
            CollectSnapshots --> WaitUpdate
        }

        state RenderLoop {
            [*] --> WaitRender
            WaitRender --> RenderFrame: timer expires
            RenderFrame --> WaitRender
        }
    }

    Stopped --> [*]
Loading

Component Dependencies

graph LR
    subgraph "Component Types"
        CLIENT[client]
        RAW[rawfiles]
        DLC[dlc]
        HELPER[helper]
        LAUNCHER[launcher]
    end

    subgraph "Update Rules"
        STRICT[Strict Hash Check]
        FAST[mtime Check]
        SELF[Self-Update Flow]
    end

    CLIENT --> STRICT
    HELPER --> STRICT
    RAW --> FAST
    DLC --> FAST
    LAUNCHER --> SELF
Loading

Cache Database Schema

erDiagram
    cached_file {
        string path PK
        component_type component
        string version
        uint64 size
        int64 mtime
        string hash
    }

    component_version {
        component_type type PK
        string tag
        int64 timestamp
    }

    cached_file }|--|| component_version : "belongs to"
Loading

File State Transitions

stateDiagram-v2
    [*] --> unknown: New file detected

    unknown --> valid: Download + track()
    unknown --> missing: Not in manifest

    valid --> stale: mtime changed
    valid --> missing: File deleted

    stale --> valid: Re-download
    stale --> valid: Hash verified OK

    missing --> valid: Download + track()
    missing --> [*]: Removed from manifest
Loading

GitHub API Request Flow

sequenceDiagram
    participant C as Caller
    participant API as github_api
    participant SSL as SSL Context
    participant NET as Network
    participant GH as api.github.com

    C->>API: fetch_latest_release(owner, repo)
    API->>SSL: create_ssl_stream()

    API->>NET: async_connect()
    NET->>GH: TCP Handshake
    GH-->>NET: Connected

    API->>NET: async_handshake(ssl)
    NET->>GH: TLS Handshake
    GH-->>NET: Secure

    API->>NET: async_write(GET /repos/.../releases)
    NET->>GH: HTTP Request
    GH-->>NET: HTTP Response

    NET-->>API: github_response

    alt Rate Limited
        API-->>C: throw rate_limit_exceeded
    else Success
        API->>API: parse_release(json)
        API-->>C: github_release
    end
Loading

Manifest Merging Strategy

flowchart TD
    subgraph "Sources"
        CLIENT_M[Client Manifest]
        RAW_M[Rawfiles Manifest]
        GH_ASSETS[GitHub Assets]
    end

    subgraph "Index Building"
        HASH_IDX[Hash Index]
        ARCH_IDX[Archive Index]
        FILE_IDX[File Index]
    end

    subgraph "Merge"
        INJECT[Inject Assets]
        MERGED[Unified Manifest]
    end

    CLIENT_M --> HASH_IDX
    RAW_M --> HASH_IDX
    RAW_M --> ARCH_IDX
    RAW_M --> FILE_IDX

    GH_ASSETS --> INJECT
    HASH_IDX --> INJECT
    ARCH_IDX --> INJECT
    FILE_IDX --> INJECT

    INJECT --> MERGED
    CLIENT_M --> MERGED
Loading

Archive Extraction Flow

flowchart TD
    DL[Downloaded ZIP] --> CHECK{In archive map?}

    CHECK -->|No| SKIP[Skip extraction]
    CHECK -->|Yes| EXTRACT[miniz extract]

    EXTRACT --> FILES[Extracted files]
    FILES --> TRACK[track files in DB]
    TRACK --> CLEANUP[Remove ZIP]

    EXTRACT -->|Error| FAIL[throw runtime_error]
Loading

Proton Launch Workflow

flowchart TD
    START[proton_coordinator::complete_launch]

    START --> DETECT[detect_proton_versions]
    DETECT --> VERSIONS{Versions found?}

    VERSIONS -->|No| ERROR[Return false]
    VERSIONS -->|Yes| BEST[find_best_version]

    BEST --> PREPARE[prepare_environment]

    subgraph "Environment Setup"
        PREPARE --> COMPAT[Set STEAM_COMPAT_DATA_PATH]
        COMPAT --> CLIENT[Set STEAM_COMPAT_CLIENT_INSTALL_PATH]
        CLIENT --> APPID[Create steam_appid.txt]
    end

    APPID --> SETUP[setup_for_launch]
    SETUP --> GHOST[Check Steam via ghost process]

    GHOST --> RUNNING{Steam Running?}
    RUNNING -->|No| STARTSTEAM[start_steam]
    RUNNING -->|Yes| LAUNCH

    STARTSTEAM --> LAUNCH[launch via Proton]
    LAUNCH --> EXEC["proton run executable.exe"]
Loading

HTTP Client Connection Flow

sequenceDiagram
    participant C as Caller
    participant S as http_session
    participant R as Resolver
    participant SSL as SSL Context
    participant TCP as TCP Socket

    C->>S: request(url)

    S->>S: parse_url()
    S->>R: async_resolve(host, port)
    R-->>S: endpoints[]

    loop Try each endpoint
        S->>TCP: async_connect(endpoint)
        alt Success
            TCP-->>S: connected
        else Timeout
            S->>TCP: try next endpoint
        end
    end

    alt HTTPS
        S->>SSL: async_handshake()
        SSL-->>S: secure
    end

    S->>TCP: async_write(request)
    TCP-->>S: bytes_sent

    S->>TCP: async_read(response)
    TCP-->>S: response_data

    alt Redirect (301/302/307)
        S->>S: follow_redirect()
    else Success
        S-->>C: http_response
    end
Loading

Error Handling Flow

flowchart TD
    subgraph "Exception Sources"
        NET[Network Error]
        PARSE[Parse Error]
        FS[Filesystem Error]
        RATE[Rate Limit]
    end

    subgraph "Propagation"
        CORO[Coroutine Exception]
        SPAWN[co_spawn callback]
    end

    subgraph "Handling"
        LOG[Log to stderr]
        CODE[Set exit_code]
        STOP[ioc.stop]
    end

    NET --> CORO
    PARSE --> CORO
    FS --> CORO
    RATE --> CORO

    CORO --> SPAWN
    SPAWN --> LOG
    LOG --> CODE
    CODE --> STOP
Loading

Manifest Structure

classDiagram
    class manifest {
        +vector~manifest_file~ files
        +vector~manifest_archive~ archives
        +hash_type hash
    }

    class manifest_file {
        +hash_type hash
        +uint64 size
        +string path
        +optional~string~ asset_name
        +optional~string~ archive_name
    }

    class manifest_archive {
        +hash_type hash
        +uint64 size
        +string name
        +string url
        +compression_type compression
        +vector~manifest_file~ files
    }

    class hash_type {
        +hash_algorithm algorithm
        +string value
        +verify(buffer) bool
    }

    manifest "1" *-- "*" manifest_file
    manifest "1" *-- "*" manifest_archive
    manifest_archive "1" *-- "*" manifest_file
    manifest_file --> hash_type
    manifest_archive --> hash_type
Loading

Template Hierarchy

flowchart TB
    subgraph "Traits Layer"
        DT[download_task_traits]
        DMT[download_manager_traits]
        PMT[progress_manager_traits]
        RT[reconciler_traits]
        HT[http_client_traits]
    end

    subgraph "Basic Templates"
        BDT[basic_download_task]
        BDM[basic_download_manager]
        BPM[basic_progress_manager]
        BR[basic_reconciler]
        BHC[basic_http_client]
    end

    subgraph "Concrete Types"
        TASK[download_task]
        MGR[download_manager]
        PROG[progress_manager]
        REC[reconciler]
        HTTP[http_client]
    end

    DT --> BDT
    DMT --> BDM
    PMT --> BPM
    RT --> BR
    HT --> BHC

    BDT --> TASK
    BDM --> MGR
    BPM --> PROG
    BR --> REC
    BHC --> HTTP
Loading

Two-Pass Verification

sequenceDiagram
    participant C as Controller
    participant R as Reconciler
    participant D as Downloads
    participant FS as Filesystem

    Note over C,FS: First Pass - Trust Download Results

    C->>R: plan(manifest)
    R-->>C: items[]

    loop Each download item
        C->>D: queue_download()
    end

    C->>D: execute_all()
    D-->>C: completion

    Note over C,FS: Second Pass - Verify Filesystem

    C->>D: clear()
    C->>R: plan(manifest) again

    R->>FS: stat each file
    FS-->>R: file_state

    alt Any missing/stale
        R-->>C: new items[]
        C->>D: re-download stragglers
    else All valid
        R-->>C: empty plan
        C->>R: stamp(versions)
    end
Loading

Update State Machine

stateDiagram-v2
    [*] --> idle: Constructor

    idle --> checking: check_for_updates()
    checking --> idle: up_to_date
    checking --> idle: update_available
    checking --> failed: check_failed

    idle --> downloading: install_update()
    downloading --> installing: download complete
    downloading --> failed: download error

    installing --> verifying: extract complete
    verifying --> restarting: verify OK
    verifying --> failed: verify failed

    restarting --> [*]: exec() new binary
    failed --> idle: reset()
Loading

Rate Limit Handling

flowchart TD
    REQ[GitHub API Request] --> RESP{Response Code?}

    RESP -->|200-299| SUCCESS[Parse & Return]
    RESP -->|403/429| RATE[Rate Limited]
    RESP -->|Other| ERROR[HTTP Error]

    RATE --> HEADERS[Extract X-RateLimit-*]
    HEADERS --> CALC[Calculate wait time]
    CALC --> WAIT{Wait or Fail?}

    WAIT -->|Retry enabled| SLEEP[co_await timer]
    SLEEP --> REQ

    WAIT -->|No retry| THROW[throw rate_limit_exceeded]

    ERROR --> THROW2[throw http_error]
Loading

Coordinator Ownership

flowchart TB
    subgraph "launcher_controller (owns)"
        IOC[io_context&]
        CTX[runtime_context]
    end

    subgraph "Coordinators (owned)"
        GH[github_coordinator]
        HTTP[http_coordinator]
        DL[download_coordinator]
        PROG[progress_coordinator]
        CACHE[cache_coordinator]
    end

    subgraph "Managers (owned by coordinators)"
        GH --> GHAPI[github_api]
        HTTP --> HTTPC[http_client]
        DL --> DLM[download_manager]
        PROG --> PM[progress_manager]
        CACHE --> REC[reconciler]
        CACHE --> DB[cache_database]
    end

    IOC -.->|ref| GH
    IOC -.->|ref| HTTP
    IOC -.->|ref| DL
    IOC -.->|ref| PROG
    IOC -.->|ref| CACHE
Loading

Version String Format (build2)

flowchart LR
    subgraph "Version Components"
        MAJOR[major]
        MINOR[minor]
        PATCH[patch]
        PRE[pre_release]
        SNAP[snapshot_sn]
        SNAPID[snapshot_id]
    end

    subgraph "Examples"
        R1["1.1.0 (release)"]
        R2["1.2.0-a.1 (alpha)"]
        R3["1.2.0-b.2 (beta)"]
        R4["1.2.0-a.1.z (dev snapshot)"]
        R5["1.2.0-a.1.20260201.fe4660 (commit)"]
    end

    MAJOR --> R1
    MINOR --> R1
    PATCH --> R1

    PRE --> R2
    PRE --> R3

    SNAP --> R4
    SNAPID --> R5
Loading

Cache Directory Resolution

flowchart TD
    START[resolve_cache_root] --> PLATFORM{Platform?}

    PLATFORM -->|Windows| WIN_CHECK{LOCALAPPDATA?}
    WIN_CHECK -->|Set| WIN_LOCAL["$LOCALAPPDATA/iw4x"]
    WIN_CHECK -->|Unset| WIN_APP{APPDATA?}
    WIN_APP -->|Set| WIN_ROAM["$APPDATA/iw4x"]
    WIN_APP -->|Unset| WIN_CWD["./.iw4x"]

    PLATFORM -->|macOS| MAC_CHECK{HOME?}
    MAC_CHECK -->|Set| MAC_PATH["~/Library/Application Support/iw4x"]
    MAC_CHECK -->|Unset| MAC_CWD["./.iw4x"]

    PLATFORM -->|Linux| XDG_CHECK{XDG_CACHE_HOME?}
    XDG_CHECK -->|Set| XDG_PATH["$XDG_CACHE_HOME/iw4x"]
    XDG_CHECK -->|Unset| HOME_CHECK{HOME?}
    HOME_CHECK -->|Set| LINUX_CACHE["~/.cache/iw4x"]
    HOME_CHECK -->|Unset| LINUX_CWD["./.iw4x"]

    WIN_LOCAL --> SCOPE
    WIN_ROAM --> SCOPE
    WIN_CWD --> SCOPE
    MAC_PATH --> SCOPE
    MAC_CWD --> SCOPE
    XDG_PATH --> SCOPE
    LINUX_CACHE --> SCOPE
    LINUX_CWD --> SCOPE

    SCOPE{Has scope path?}
    SCOPE -->|Yes| DIGEST["+ path_digest(scope)"]
    SCOPE -->|No| MKDIR

    DIGEST --> MKDIR[create_directories]

    MKDIR --> SUCCESS{Created?}
    SUCCESS -->|Yes| RETURN[Return path]
    SUCCESS -->|No| FALLBACK["./.iw4x fallback"]
    FALLBACK --> RETURN
Loading

EWMA Speed Calculation

flowchart LR
    subgraph "Input"
        BYTES[current_bytes]
        TIME[current_time]
    end

    subgraph "Ring Buffer"
        S1[sample 0]
        S2[sample 1]
        S3[sample ...]
        S4[sample N-1]
    end

    subgraph "Calculation"
        DELTA_B[Δ bytes]
        DELTA_T[Δ time]
        INSTANT[instant_speed]
        EWMA["EWMA: α×new + (1-α)×old"]
    end

    BYTES --> DELTA_B
    TIME --> DELTA_T
    DELTA_B --> INSTANT
    DELTA_T --> INSTANT

    INSTANT --> S1
    S1 --> S2
    S2 --> S3
    S3 --> S4

    S4 --> EWMA
    EWMA --> OUTPUT[smoothed speed]
Loading

Progress Rendering (FTXUI)

flowchart TB
    subgraph "Data Collection"
        ENTRIES[progress_entries]
        SNAP[Create snapshots]
        CTX[render_context]
    end

    subgraph "FTXUI Components"
        ITEMS[render_item per entry]
        SUMMARY[render_summary]
        LOGS[render_logs]
        STATUS[render_status]
    end

    subgraph "Terminal Output"
        VBOX[vbox layout]
        SCREEN[screen.Post]
        TTY[Terminal]
    end

    ENTRIES --> SNAP
    SNAP --> CTX

    CTX --> ITEMS
    CTX --> SUMMARY
    CTX --> LOGS
    CTX --> STATUS

    ITEMS --> VBOX
    SUMMARY --> VBOX
    LOGS --> VBOX
    STATUS --> VBOX

    VBOX --> SCREEN
    SCREEN --> TTY
Loading

Update Installation Sequence

sequenceDiagram
    participant I as update_installer
    participant HTTP as http_client
    participant TMP as Temp Directory
    participant FS as Filesystem
    participant EXE as Running Executable

    I->>TMP: create staging directory
    I->>HTTP: download(asset_url)
    HTTP-->>TMP: write binary to temp

    I->>I: verify_size()

    alt Hash provided
        I->>TMP: compute BLAKE3
        I->>I: compare hashes
    end

    Note over I,EXE: Windows: Cannot overwrite running exe

    I->>EXE: rename current → .backup
    I->>TMP: move new → current location
    I->>FS: set executable permissions

    alt Success
        I-->>I: update_result{success=true}
    else Failure
        I->>EXE: rollback: restore .backup
        I-->>I: update_result{success=false}
    end
Loading

Parallel Download Scheduling

flowchart TD
    QUEUE[Task Queue] --> SCHED{Active < max_parallel?}

    SCHED -->|Yes| START[Start next task]
    SCHED -->|No| WAIT[Wait for completion]

    START --> ACTIVE[Active Tasks Pool]
    WAIT --> LISTEN[Listen for completion event]

    ACTIVE --> PROGRESS[on_progress callbacks]
    ACTIVE --> COMPLETE{Task done?}

    COMPLETE -->|Success| SUCCESS[Mark completed]
    COMPLETE -->|Failed| FAILED[Mark failed]

    SUCCESS --> CALLBACK[on_task_complete]
    FAILED --> CALLBACK

    CALLBACK --> SCHED

    LISTEN --> COMPLETE
Loading

Platform-Specific Binary Selection

flowchart TD
    RELEASE[GitHub Release Assets] --> SCAN[Scan asset names]

    SCAN --> MATCH{Match pattern?}

    subgraph "Windows Patterns"
        W1["*-win64.exe"]
        W2["*-windows-x64.exe"]
        W3["*.exe"]
    end

    subgraph "Linux Patterns"
        L1["*-linux-x64"]
        L2["*-linux64"]
        L3["* (no extension)"]
    end

    subgraph "macOS Patterns"
        M1["*-macos-x64"]
        M2["*-darwin-x64"]
        M3["*.app.zip"]
    end

    MATCH -->|Windows| W1
    MATCH -->|Linux| L1
    MATCH -->|macOS| M1

    W1 --> SELECT[Select asset]
    W2 --> SELECT
    L1 --> SELECT
    L2 --> SELECT
    M1 --> SELECT
    M2 --> SELECT

    SELECT --> URL[browser_download_url]
Loading

Ghost Process Pattern (Steam Check)

sequenceDiagram
    participant P as proton_coordinator
    participant GHOST as steam.exe (helper)
    participant WINE as Proton/Wine
    participant STEAM as Steam Client

    Note over P,STEAM: Check if Steam API is available

    P->>WINE: Launch steam.exe --check
    WINE->>GHOST: Execute in Wine prefix

    GHOST->>GHOST: SteamAPI_Init()

    alt Steam Running
        GHOST-->>WINE: Exit code 0
        WINE-->>P: steam_running
    else Steam Not Running
        GHOST-->>WINE: Exit code 1
        WINE-->>P: steam_not_running
        P->>P: start_steam()
    end
Loading

ODB Database Operations

flowchart LR
    subgraph "Operations"
        PERSIST[db.persist]
        UPDATE[db.update]
        ERASE[db.erase]
        QUERY[db.query]
    end

    subgraph "Transactions"
        BEGIN[transaction t]
        COMMIT[t.commit]
        ROLLBACK[t.rollback]
    end

    subgraph "Tables"
        CF[(cached_files)]
        CV[(component_versions)]
    end

    PERSIST --> BEGIN
    UPDATE --> BEGIN
    ERASE --> BEGIN
    QUERY --> BEGIN

    BEGIN --> CF
    BEGIN --> CV

    CF --> COMMIT
    CV --> COMMIT
Loading

Controller Run Flow

flowchart TD
    START[controller.run] --> REMOTE[resolve_remote_state]

    subgraph "Parallel API Calls"
        C[fetch client release]
        R[fetch rawfiles release]
        H[fetch helper release]
        D[fetch DLC manifest]
    end

    REMOTE --> C & R & H & D
    C & R & H & D --> MERGE[Build remote_state]

    MERGE --> RECONCILE[reconcile_artifacts]

    subgraph "Reconciliation"
        PLAN[Generate plan]
        DOWNLOAD[Execute downloads]
        VERIFY[Two-pass verify]
        EXTRACT[Extract archives]
        STAMP[Stamp versions]
    end

    RECONCILE --> PLAN --> DOWNLOAD --> VERIFY --> EXTRACT --> STAMP

    STAMP --> PAYLOAD[execute_payload]

    subgraph "Launch"
        NATIVE[Native execution]
        PROTON[Proton execution]
    end

    PAYLOAD -->|Windows| NATIVE
    PAYLOAD -->|Linux| PROTON

    NATIVE --> EXIT[Return exit_code]
    PROTON --> EXIT
Loading

Retry Backoff Strategy

flowchart TD
    REQ[HTTP Request] --> RESULT{Success?}

    RESULT -->|Yes| DONE[Return response]
    RESULT -->|No| RETRY{Retries left?}

    RETRY -->|No| FAIL[Throw error]
    RETRY -->|Yes| BACKOFF[Calculate delay]

    BACKOFF --> DELAY["delay = base × 2^attempt"]
    DELAY --> JITTER["+ random jitter"]
    JITTER --> CAP["min(delay, max_delay)"]

    CAP --> WAIT[co_await timer]
    WAIT --> REQ
Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment