|
| 1 | +# Data Sources and Ingestion |
| 2 | + |
| 3 | +Open Cinema Index (OCI) uses a structured system to manage data ingestion from various external providers. This document explains the core components of the ingestion system: Data Sources, Capabilities, Refresh Policies, Rate Limits, and Runs. |
| 4 | + |
| 5 | +## Data Sources |
| 6 | + |
| 7 | +A `DataSource` represents an external entity that provides film-related data. Each source is uniquely identified by its name and has several configuration properties: |
| 8 | + |
| 9 | +- **name**: A unique identifier for the source (e.g., `tmdb`, `wikidata`). |
| 10 | +- **kind**: The protocol used to communicate with the source (`rest`, `graphql`, `file`). |
| 11 | +- **base_url**: The root URL for API requests. |
| 12 | +- **user_agent**: A custom User-Agent string to be used for requests to this source. |
| 13 | +- **enabled**: A boolean flag to quickly enable or disable a source without deleting its configuration. |
| 14 | + |
| 15 | +Data sources also track their execution history via `last_run_started_at`, `last_run_completed_at`, and `last_error`. |
| 16 | + |
| 17 | +## Capabilities |
| 18 | + |
| 19 | +`DataSourceCapability` defines what kind of data a specific `DataSource` is able to provide and how to access it. This allows the OCI pipeline to intelligently route requests to the most appropriate sources and construct correct URLs. |
| 20 | + |
| 21 | +Properties: |
| 22 | +- **capability**: The identifier for the type of data (e.g., `films`, `people`, `assets`, `updates`). |
| 23 | +- **endpoint_path**: A relative path or query template that is appended to the `base_url` to fetch the data. |
| 24 | +- **payload_mapping**: A JSON-defined mapping that tells OCI how to translate the external response into its canonical schema. |
| 25 | + |
| 26 | +Example paths: |
| 27 | +- `/movie/{id}` for TMDB films. |
| 28 | +- `?query={query}` for Wikidata SPARQL. |
| 29 | + |
| 30 | +### Response Mapping |
| 31 | + |
| 32 | +The `payload_mapping` field allows OCI to handle "unknown" sources by defining how to extract data from their responses. It typically maps JSON paths or keys from the source to OCI fields. |
| 33 | + |
| 34 | +Example mapping for a `films` capability: |
| 35 | +```json |
| 36 | +{ |
| 37 | + "title": "original_title", |
| 38 | + "runtime_minutes": "runtime", |
| 39 | + "original_language": "iso_639_1" |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +This mapping is used during the `normalize` phase of the ingestion pipeline. |
| 44 | + |
| 45 | +Common capabilities include: |
| 46 | +- `films`: Can provide basic film metadata. |
| 47 | +- `people`: Can provide data about cast and crew. |
| 48 | +- `assets`: Can provide URLs for posters, backdrops, etc. |
| 49 | +- `updates`: Can provide a stream of recently changed records. |
| 50 | + |
| 51 | +## Refresh Policies |
| 52 | + |
| 53 | +The `DataSourceRefreshPolicy` determines how often data from a source should be updated and how to handle incremental fetches. |
| 54 | + |
| 55 | +- **default_refresh_interval_minutes**: The standard time to wait before re-fetching a record from this source. |
| 56 | +- **max_record_age_days**: The maximum age a record can reach before it is considered stale, regardless of the refresh interval. |
| 57 | +- **incremental_cursor_field**: The field used to track progress during incremental ingestion (e.g., a timestamp or an ID). |
| 58 | +- **supports_webhook**: Indicates if the source can push updates to OCI via webhooks. |
| 59 | + |
| 60 | +## Rate Limits |
| 61 | + |
| 62 | +To be a good citizen of the web and avoid being blocked, OCI strictly adheres to rate limits defined in `DataSourceRateLimit`. |
| 63 | + |
| 64 | +- **window_seconds**: The duration of the rate limit window (e.g., 60 seconds for a "per minute" limit). |
| 65 | +- **max_calls**: The maximum number of requests allowed within the window. |
| 66 | +- **burst**: The number of requests allowed in a single burst, even if it exceeds the average rate momentarily. |
| 67 | +- **retry_delay_seconds**: How long to wait before retrying if a rate limit is hit. |
| 68 | + |
| 69 | +Multiple rate limits can be applied to a single source (e.g., 40 requests per 10 seconds AND 10,000 requests per day). |
| 70 | + |
| 71 | +## Runs |
| 72 | + |
| 73 | +A `DataSourceRun` represents a single execution of the ingestion process for a specific source. It provides observability and audit trails for data ingestion. |
| 74 | + |
| 75 | +- **started_at** / **completed_at**: Timestamps for the duration of the run. |
| 76 | +- **status**: The outcome of the run (`started`, `success`, `failed`). |
| 77 | +- **error**: If the run failed, the error message or stack trace. |
| 78 | +- **items_fetched**: Total number of records retrieved from the source. |
| 79 | +- **items_processed**: Total number of records successfully integrated into OCI. |
| 80 | + |
| 81 | +The `duration` of a run is calculated as the difference between `completed_at` and `started_at`. |
0 commit comments