rearranged directory structure, automaterialize to automationCondition
This commit is contained in:
parent
dcff5c78e7
commit
11003a8bda
11 changed files with 38 additions and 31 deletions
85
user_code/resources.py
Normal file
85
user_code/resources.py
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
from dagster import ConfigurableResource
|
||||
import requests
|
||||
from typing import Optional
|
||||
from time import sleep
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class MobilityDatabaseAPI(ConfigurableResource):
|
||||
"""Resource for interacting with the Mobility Database API with OAuth2 token management."""
|
||||
|
||||
base_url: str = "https://api.mobilitydatabase.org"
|
||||
refresh_token: str # Long-lived refresh token
|
||||
rate_limit_delay: float = 0.5 # Seconds between requests
|
||||
|
||||
# These will be set at runtime, not in config
|
||||
_access_token: Optional[str] = None
|
||||
_token_expires_at: Optional[datetime] = None
|
||||
|
||||
def _get_access_token(self) -> str:
|
||||
"""
|
||||
Get a valid access token, refreshing if necessary.
|
||||
Access tokens are valid for 1 hour.
|
||||
"""
|
||||
# If we have a token and it's not expired (with 5 min buffer), use it
|
||||
if self._access_token and self._token_expires_at:
|
||||
if datetime.now() < self._token_expires_at - timedelta(minutes=5):
|
||||
return self._access_token
|
||||
|
||||
# Need to get a new token
|
||||
logger.info("Fetching new access token from Mobility Database API")
|
||||
|
||||
url = f"{self.base_url}/v1/tokens"
|
||||
headers = {"Content-Type": "application/json"}
|
||||
data = {"refresh_token": self.refresh_token}
|
||||
|
||||
try:
|
||||
response = requests.post(url, headers=headers, json=data, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
token_data = response.json()
|
||||
self._access_token = token_data.get("access_token")
|
||||
|
||||
# Tokens are valid for 1 hour
|
||||
self._token_expires_at = datetime.now() + timedelta(hours=1)
|
||||
|
||||
logger.info("Successfully obtained new access token")
|
||||
return self._access_token
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Error fetching access token: {e}")
|
||||
raise RuntimeError(f"Failed to obtain access token: {e}")
|
||||
|
||||
def get_feed_info(self, feed_id: str) -> dict:
|
||||
"""
|
||||
Fetch feed information from the Mobility Database API.
|
||||
|
||||
Args:
|
||||
feed_id: The MDB feed ID (e.g., 'mdb-394')
|
||||
|
||||
Returns:
|
||||
Dictionary containing feed information
|
||||
"""
|
||||
access_token = self._get_access_token()
|
||||
|
||||
url = f"{self.base_url}/v1/feeds/{feed_id}"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {access_token}"
|
||||
}
|
||||
|
||||
logger.info(f"Fetching feed info for {feed_id}")
|
||||
|
||||
try:
|
||||
response = requests.get(url, headers=headers, timeout=30)
|
||||
response.raise_for_status()
|
||||
|
||||
# Rate limiting
|
||||
sleep(self.rate_limit_delay)
|
||||
|
||||
return response.json()
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.error(f"Error fetching feed {feed_id}: {e}")
|
||||
raise
|
||||
Loading…
Add table
Add a link
Reference in a new issue