Skip to main content

Python client library for the Spark Fuse GPU compute API

Project description

Spark Fuse Messenger

Python client and CLI for the Spark Fuse on-demand GPU compute API.

Submit Docker-image jobs to cloud GPUs, stream live logs, and pull outputs back from ShareSync — all from Python or the command line.

Requirements

  • Python 3.12+
  • A Spark Fuse account with API credentials

Installation

Install from PyPI:

pip install spark-fuse-messenger

Or clone and run from source with uv:

git clone https://github.com/VFXGuru/spark-fuse-messenger
cd spark-fuse-messenger
uv sync

API reference

This client implements the Spark Fuse REST API. The API is documented in spark-fuse-api-v124.md, a file provided by Spark Cloud Studio to its customers. That document is not redistributed in this repo. If you want to reference it locally, place your own copy in the project root.

Copy .env.example to .env and fill in your credentials:

SPARK_HOST=https://api.prod.aapse1.sparkcloud.studio
SPARK_EMAIL=you@yourcompany.com
SPARK_PASSWORD=your-password

.env is gitignored and never committed.

Activate the venv or prefix every command with uv run:

.venv\Scripts\activate        # Windows
source .venv/bin/activate     # macOS / Linux

CLI commands

# Verify credentials (free)
spark-fuse login

# List available GPU SKUs (free)
spark-fuse skus

# Cost estimate — rate only, or with runtime (free)
spark-fuse estimate g4dn.xlarge --runtime 3600

# Submit a job
spark-fuse submit --image alpine:3 --command echo --command hello --instance-type g4dn.xlarge

# Submit with a local input directory (auto tar+upload)
spark-fuse submit --image pytorch/pytorch:2.7.1-cuda12.8-cudnn9-runtime \
  --command python3 --command /input/run.py \
  --instance-type g7e.2xlarge --input-dir ./my-scripts

# Poll status
spark-fuse status <job-id>

# List all jobs (optional tag filters)
spark-fuse list
spark-fuse list --tag ci --tag training          # AND filter
spark-fuse list --tags-any "ci,staging"          # OR filter

# Stream live logs (connect immediately after submit — no replay)
spark-fuse logs <job-id>

# Cancel (idempotent)
spark-fuse cancel <job-id>

# Download all output files
spark-fuse download <job-id> ./outputs

# Persistent-compute sessions: pre-warm one instance and run jobs back to back (§13)
spark-fuse instance prepare g7e.2xlarge --hold-seconds 1800   # prints a handle
spark-fuse instance status <handle>                           # poll until 'ready'
spark-fuse instance release <handle>                          # tear down

Submit jobs onto a prepared session by passing the handle: spark-fuse submit ... --instance-handle <handle> (or instance_handle= on client.submit). Each job lands on that same warm instance with no cold start.

Python API

from spark_fuse import SparkFuseClient

with SparkFuseClient(host="...", email="...", password="...") as client:
    client.login()

    resp = client.submit(
        image="alpine:3",
        command=["echo", "hello"],
        instance_type="g4dn.xlarge",
    )
    job_id = resp.job_id

    for event in client.stream_logs(job_id):
        print(event)

    job = client.get_job(job_id)
    print(job.status, job.exit_code)

Sessions (warm-instance pool)

Pre-warm a single instance and route several jobs to it so each job skips the cold start and image pull. The hold_seconds clock starts when the instance becomes ready and re-arms after each job, so it is an idle ceiling, not a total-session ceiling.

from spark_fuse import SparkFuseClient

with SparkFuseClient(host="...", email="...", password="...") as client:
    client.login()

    # context manager: prepare -> wait_until_ready -> yield -> release
    with client.session(instance_type="g7e.2xlarge", hold_seconds=600) as sess:
        handle = sess.instance_handle
        for workflow in my_workflows:
            resp = client.submit(..., instance_handle=handle)
            # poll resp.job_id to completion as normal

Or manage the lifecycle manually:

sess = client.prepare_instance(instance_type="g7e.2xlarge", hold_seconds=600)
sess = client.wait_until_ready(sess.instance_handle)   # polls until ready
# ... submit jobs with instance_handle=sess.instance_handle ...
client.release_instance(sess.instance_handle)

Error typesfrom spark_fuse import ...:

Exception When raised
NoWarmPoolCapacityError prepare_instance returns HTTP 503 (no warm pool slot available)
SessionFailedError Instance reaches terminal failed status
SessionNotFoundError get_instance or release_instance returns HTTP 404
SessionConflictError release_instance returns HTTP 409 (state conflict)
SessionError Base class for all of the above

Session affinity in the ComfyUI bridge — the bridge's render queue accepts a session_affinity setting ("preferred" or "required"). With "preferred" (the default), the queue retries on NoWarmPoolCapacityError and falls back to independent submits if no slot becomes available. With "required", it aborts the queue instead of falling back. An explicit "off" mode (always independent submits, never attempt prepare) is a known future toggle, not yet implemented.

Running tests

All tests mock HTTP — no network calls required:

uv run pytest -v

Project structure

src/spark_fuse/
├── client.py      — SparkFuseClient (all API methods)
├── auth.py        — login + token management
├── sharesync.py   — WebDAV: tar+upload, PROPFIND, streaming download
├── logs.py        — SSE log streaming
├── errors.py      — typed exceptions
├── models.py      — dataclasses + enums (JobStatus, ErrorCode, …)
└── cli.py         — Typer CLI

tests/             — unit tests (HTTP mocked)

License

MIT — Copyright (c) 2026 VFXGuru

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spark_fuse_messenger-0.4.0.tar.gz (37.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spark_fuse_messenger-0.4.0-py3-none-any.whl (27.6 kB view details)

Uploaded Python 3

File details

Details for the file spark_fuse_messenger-0.4.0.tar.gz.

File metadata

  • Download URL: spark_fuse_messenger-0.4.0.tar.gz
  • Upload date:
  • Size: 37.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for spark_fuse_messenger-0.4.0.tar.gz
Algorithm Hash digest
SHA256 2dda969cae07e6f3a311ef1394ff1b7684f77741de190c53865a3cb82448a978
MD5 abf5a7df49fac8002dfda82514efadd0
BLAKE2b-256 9a5257a5107a9ab4ed9990fa80105e925737d282800fe76d38422fe9511b9f75

See more details on using hashes here.

File details

Details for the file spark_fuse_messenger-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for spark_fuse_messenger-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dbdfb0ea379d53be1c7d2aab582a58a6d1e69adcfa299abe77b3fff0dca10883
MD5 a87231a8f24ea4e458fa2c845c798065
BLAKE2b-256 28ebc747b675d9a12150a466bdc19a3f7ae63c46f0d3e4bde717f04d56c4ffa2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page