Skip to content

Commit

Permalink
Add Max Age to get_latest_result (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
bh2smith authored Sep 14, 2023
1 parent 02ea964 commit 2f0b384
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 5 deletions.
26 changes: 23 additions & 3 deletions dune_client/api/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
Extended functionality for the ExecutionAPI
"""
from __future__ import annotations

import logging
import time

from io import BytesIO
from typing import Union, Optional, Any

Expand All @@ -19,6 +22,9 @@
)
from dune_client.query import QueryBase, parse_query_object_or_id
from dune_client.types import QueryParameter
from dune_client.util import age_in_hours

THREE_MONTHS_IN_HOURS = 2191


class ExtendedAPI(ExecutionAPI, QueryAPI):
Expand Down Expand Up @@ -76,13 +82,17 @@ def run_query_dataframe(
data = self.run_query_csv(query, ping_frequency, performance).data
return pandas.read_csv(data)

def get_latest_result(self, query: Union[QueryBase, str, int]) -> ResultsResponse:
def get_latest_result(
self,
query: Union[QueryBase, str, int],
max_age_hours: int = THREE_MONTHS_IN_HOURS,
) -> ResultsResponse:
"""
GET the latest results for a query_id without re-executing the query
(doesn't use execution credits)
:param query: :class:`Query` object OR query id as string or int
:param max_age_hours: re-executes the query if result is older than max_age_hours
https://dune.com/docs/api/api-reference/get-results/latest-results
"""
params, query_id = parse_query_object_or_id(query)
Expand All @@ -91,7 +101,17 @@ def get_latest_result(self, query: Union[QueryBase, str, int]) -> ResultsRespons
params=params,
)
try:
return ResultsResponse.from_dict(response_json)
results = ResultsResponse.from_dict(response_json)
last_run = results.times.execution_ended_at
if last_run and age_in_hours(last_run) > max_age_hours:
# Query older than specified max age
logging.info(
f"results (from {last_run}) older than {max_age_hours} hours, re-running query"
)
results = self.run_query(
query if isinstance(query, QueryBase) else QueryBase(query_id)
)
return results
except KeyError as err:
raise DuneError(response_json, "ResultsResponse", err) from err

Expand Down
10 changes: 9 additions & 1 deletion dune_client/util.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Utility methods for package."""
from datetime import datetime
from datetime import datetime, timezone
from typing import Optional

import pkg_resources
Expand All @@ -20,3 +20,11 @@ def get_package_version(package_name: str) -> Optional[str]:
return pkg_resources.get_distribution(package_name).version
except pkg_resources.DistributionNotFound:
return None


def age_in_hours(timestamp: datetime) -> float:
"""
Returns the time (in hours) between now and `timestamp`
"""
result_age = datetime.now(timezone.utc) - timestamp
return result_age.total_seconds() / (60 * 60)
9 changes: 8 additions & 1 deletion tests/unit/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime
import unittest
from dune_client.util import get_package_version
from dune_client.util import get_package_version, age_in_hours


class TestUtils(unittest.TestCase):
Expand All @@ -11,3 +12,9 @@ def test_package_version_some(self):
def test_package_version_none(self):
# Can't self refer (this should only work when user has dune-client installed).
self.assertIsNone(get_package_version("unittest"))

def test_age_in_hours(self):
march_ten_eighty_five = datetime.datetime(
1985, 3, 10, tzinfo=datetime.timezone.utc
)
self.assertGreaterEqual(age_in_hours(march_ten_eighty_five), 314159)

0 comments on commit 2f0b384

Please sign in to comment.