Skip to content

Async Patterns

This example demonstrates asynchronous programming patterns with the Griddy SDK.

Basic Async Usage

import asyncio
from griddy.nfl import GriddyNFL

async def main():
    nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})

    # Use async method (note the _async suffix)
    games = await nfl.games.get_games_async(
        season=2024,
        season_type="REG",
        week=1
    )

    for game in games.games:
        print(f"{game.away_team.abbreviation} @ {game.home_team.abbreviation}")

asyncio.run(main())

Concurrent Requests

Fetch multiple endpoints simultaneously:

import asyncio
from griddy.nfl import GriddyNFL

async def fetch_all_data(nfl):
    """Fetch games, passing stats, and rushing stats concurrently."""

    # Create tasks for concurrent execution
    games_task = nfl.games.get_games_async(
        season=2024,
        season_type="REG",
        week=1
    )

    passing_task = nfl.stats.passing.get_passing_stats_by_season_async(
        season=2024
    )

    rushing_task = nfl.stats.rushing.get_rushing_stats_by_season_async(
        season=2024
    )

    # Execute all tasks concurrently
    games, passing, rushing = await asyncio.gather(
        games_task,
        passing_task,
        rushing_task
    )

    return {
        'games': games,
        'passing': passing,
        'rushing': rushing
    }

async def main():
    nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})
    data = await fetch_all_data(nfl)

    print(f"Games: {len(data['games'].games)}")
    print(f"Passers: {len(data['passing'].players)}")
    print(f"Rushers: {len(data['rushing'].players)}")

asyncio.run(main())

Fetching Multiple Weeks

import asyncio
from griddy.nfl import GriddyNFL

async def get_all_season_games(nfl, season: int, season_type: str = "REG"):
    """Fetch all weeks of a season concurrently."""
    max_weeks = {"PRE": 4, "REG": 18, "POST": 4}[season_type]

    async def get_week(week: int):
        return await nfl.games.get_games_async(
            season=season,
            season_type=season_type,
            week=week
        )

    # Create tasks for all weeks
    tasks = [get_week(week) for week in range(1, max_weeks + 1)]

    # Execute all concurrently
    results = await asyncio.gather(*tasks)

    # Flatten to single list
    all_games = []
    for week_games in results:
        all_games.extend(week_games.games)

    return all_games

async def main():
    nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})

    games = await get_all_season_games(nfl, 2024, "REG")
    print(f"Total regular season games: {len(games)}")

asyncio.run(main())

Rate-Limited Concurrent Requests

import asyncio
from griddy.nfl import GriddyNFL

class AsyncRateLimiter:
    """Semaphore-based rate limiter for async requests."""

    def __init__(self, max_concurrent: int = 5):
        self.semaphore = asyncio.Semaphore(max_concurrent)

    async def acquire(self):
        await self.semaphore.acquire()

    def release(self):
        self.semaphore.release()

async def rate_limited_fetch(nfl, limiter, season, season_type, week):
    """Fetch with rate limiting."""
    await limiter.acquire()
    try:
        return await nfl.games.get_games_async(
            season=season,
            season_type=season_type,
            week=week
        )
    finally:
        limiter.release()
        await asyncio.sleep(0.1)  # Small delay between requests

async def main():
    nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})
    limiter = AsyncRateLimiter(max_concurrent=5)

    tasks = [
        rate_limited_fetch(nfl, limiter, 2024, "REG", week)
        for week in range(1, 19)
    ]

    results = await asyncio.gather(*tasks)

    total_games = sum(len(r.games) for r in results)
    print(f"Total games: {total_games}")

asyncio.run(main())

Async Generator

Stream results as they become available:

import asyncio
from griddy.nfl import GriddyNFL
from typing import AsyncGenerator, Any

async def stream_games(
    nfl,
    season: int,
    season_type: str = "REG"
) -> AsyncGenerator[Any, None]:
    """Async generator that yields games as they're fetched."""
    max_weeks = {"PRE": 4, "REG": 18, "POST": 4}[season_type]

    for week in range(1, max_weeks + 1):
        games = await nfl.games.get_games_async(
            season=season,
            season_type=season_type,
            week=week
        )

        for game in games.games:
            yield {
                'week': week,
                'game': game
            }

async def main():
    nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})

    async for data in stream_games(nfl, 2024, "REG"):
        game = data['game']
        print(f"Week {data['week']}: {game.away_team.abbreviation} @ {game.home_team.abbreviation}")

asyncio.run(main())

Async Context Manager

import asyncio
from griddy.nfl import GriddyNFL

async def main():
    # Async context manager for automatic cleanup
    async with GriddyNFL(nfl_auth={"accessToken": "your_token"}) as nfl:
        games = await nfl.games.get_games_async(
            season=2024,
            season_type="REG",
            week=1
        )

        for game in games.games:
            print(f"{game.away_team.abbreviation} @ {game.home_team.abbreviation}")

    # Resources automatically cleaned up

asyncio.run(main())

Error Handling in Async Code

import asyncio
from griddy.nfl import GriddyNFL
from griddy.core.exceptions import GriddyError, RateLimitError

async def fetch_with_retry(nfl, season, season_type, week, max_retries=3):
    """Async fetch with exponential backoff retry."""
    for attempt in range(max_retries):
        try:
            return await nfl.games.get_games_async(
                season=season,
                season_type=season_type,
                week=week
            )

        except RateLimitError as e:
            if attempt < max_retries - 1:
                wait = e.retry_after or (2 ** attempt)
                print(f"Rate limited. Waiting {wait}s...")
                await asyncio.sleep(wait)
            else:
                raise

        except GriddyError as e:
            if e.status_code and e.status_code >= 500:
                if attempt < max_retries - 1:
                    wait = 2 ** attempt
                    print(f"Server error. Waiting {wait}s...")
                    await asyncio.sleep(wait)
                else:
                    raise
            else:
                raise

async def main():
    nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})

    try:
        games = await fetch_with_retry(nfl, 2024, "REG", 1)
        print(f"Fetched {len(games.games)} games")
    except GriddyError as e:
        print(f"Failed after retries: {e.message}")

asyncio.run(main())

Processing Results Asynchronously

import asyncio
from griddy.nfl import GriddyNFL

async def process_game(game):
    """Async processing of a single game."""
    # Simulate async processing (e.g., database insert)
    await asyncio.sleep(0.01)
    return {
        'id': game.id,
        'matchup': f"{game.away_team.abbreviation} @ {game.home_team.abbreviation}",
        'status': game.game_status
    }

async def main():
    nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})

    games = await nfl.games.get_games_async(
        season=2024,
        season_type="REG",
        week=1
    )

    # Process all games concurrently
    tasks = [process_game(game) for game in games.games]
    processed = await asyncio.gather(*tasks)

    for item in processed:
        print(item)

asyncio.run(main())

Integration with Web Frameworks

FastAPI Example

from fastapi import FastAPI
from griddy.nfl import GriddyNFL

app = FastAPI()
nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})

@app.get("/games/{season}/{season_type}/{week}")
async def get_games(season: int, season_type: str, week: int):
    games = await nfl.games.get_games_async(
        season=season,
        season_type=season_type,
        week=week
    )

    return {
        "count": len(games.games),
        "games": [
            {
                "id": g.id,
                "home": g.home_team.abbreviation,
                "away": g.away_team.abbreviation,
                "status": g.game_status
            }
            for g in games.games
        ]
    }

aiohttp Example

import asyncio
from aiohttp import web
from griddy.nfl import GriddyNFL

nfl = GriddyNFL(nfl_auth={"accessToken": "your_token"})

async def get_games(request):
    season = int(request.match_info['season'])
    week = int(request.match_info['week'])

    games = await nfl.games.get_games_async(
        season=season,
        season_type="REG",
        week=week
    )

    return web.json_response({
        "count": len(games.games),
        "games": [g.id for g in games.games]
    })

app = web.Application()
app.router.add_get('/games/{season}/{week}', get_games)

if __name__ == '__main__':
    web.run_app(app)