sk examples

Basic examples
Async examples
Blocking detection
Classes
Advanced examples

Full script using sk modifiers

An end-to-end example that uses multiple modifiers together:

"""
End-to-end sk modifiers example.

Parses in-memory JSON records, repairs incomplete inputs, scores them in
background, and returns scored records.
"""

import asyncio
import json
import hashlib

from suitkaise import sk, blocking
from suitkaise.sk import FunctionTimeoutError


class TransientError(RuntimeError):
    pass


def seed_records() -> list[str]:
    """Create a mix of valid and truncated JSON payloads."""
    payloads = []
    for record_id in range(1, 11):
        record = {"id": record_id, "value": record_id * 3}
        text = json.dumps(record)
        if record_id == 4:
            text = text[:-1]  # truncate one payload to trigger repair
        payloads.append(text)
    return payloads


@sk
@blocking
def load_record(index: int, payloads: list[str]) -> dict:
    text = payloads[index]
    try:
        record = json.loads(text)
    except json.JSONDecodeError:
        # repair and retry in memory
        payloads[index] = text + "}"
        raise TransientError("Record incomplete, repaired and retrying")
    
    if "id" not in record or "value" not in record:
        raise ValueError("Missing required keys")
    
    return record


@sk
@blocking
def score_record(record: dict) -> dict:
    payload = f"{record['id']}:{record['value']}".encode()
    digest = hashlib.sha256(payload).hexdigest()
    score = int(digest[:8], 16) % 1000
    return {**record, "score": score}


async def main():
    payloads = seed_records()
    
    loader = (
        load_record.asynced()
        .retry(times=2, delay=0.1, exceptions=(TransientError,))
        .timeout(0.5)
        .rate_limit(20.0)
    )
    
    results = await asyncio.gather(
        *[loader(i, payloads) for i in range(len(payloads))],
        return_exceptions=True,
    )
    
    records = []
    for idx, result in enumerate(results):
        if isinstance(result, FunctionTimeoutError):
            print(f"Timeout: record {idx + 1}")
            continue
        if isinstance(result, Exception):
            print(f"Failed: record {idx + 1}: {result}")
            continue
        records.append(result)
    
    futures = [score_record.background()(record) for record in records]
    scored = [future.result() for future in futures]
    
    print(f"Scored {len(scored)} records")
    print("Sample:", scored[:3])


if __name__ == "__main__":
    asyncio.run(main())