Skip to content

Commit

Permalink
NOMERGE: Log number of bytes downloaded per day, if statistics table …
Browse files Browse the repository at this point in the history
…created manually
  • Loading branch information
davidfstr committed Feb 3, 2024
1 parent f96a12c commit 267cf51
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
53 changes: 51 additions & 2 deletions src/crystal/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
get_column_names_of_table,
get_index_names,
is_no_such_column_error_for,
is_no_such_table_error_for,
)
from crystal.util.ellipsis import Ellipsis, EllipsisType
from crystal.util import gio
Expand All @@ -54,7 +55,7 @@
from crystal.util.xgc import gc_disabled
from crystal.util.xos import is_linux, is_mac_os, is_windows
from crystal.util import xshutil
from crystal.util.xsqlite3 import sqlite_has_json_support
from crystal.util.xsqlite3 import is_database_closed_error, sqlite_has_json_support
from crystal.util.xthreading import (
bg_affinity, bg_call_later, fg_affinity, fg_call_and_wait, fg_call_later,
is_foreground_thread,
Expand Down Expand Up @@ -2461,7 +2462,18 @@ def fg_task() -> None:
suffix='.body',
dir=os.path.join(project.path, Project._TEMPORARY_DIRNAME),
delete=False) as body_file:
xshutil.copyfileobj_readinto(body_stream, body_file)
try:
xshutil.copyfileobj_readinto(body_stream, body_file)
finally:
try:
ResourceRevision._log_bytes_downloaded(
body_file.tell(),
resource.project)
except sqlite3.ProgrammingError as e:
if is_database_closed_error(e):
pass
else:
raise
body_file_downloaded_ok = True
else:
body_file = None
Expand Down Expand Up @@ -3138,6 +3150,43 @@ def delete(self):

self.resource.already_downloaded_this_session = False

# === Logging ===

@staticmethod
def _log_bytes_downloaded(num_bytes_downloaded: int, project: Project) -> None:
"""
Logs that the specified number of bytes were downloaded,
if the following statistics table exists:
create table statistics (date text primary key asc, num_bytes_downloaded int default 0)
"""
def fg_task() -> None:
today_local_tz = datetime.date.today() # capture

try:
c = project._db.cursor()
c.execute(
'insert into statistics '
'(date, num_bytes_downloaded) '
'values (?, ?) '
'on conflict (date) do '
'update '
'set num_bytes_downloaded = num_bytes_downloaded + ?',
(str(today_local_tz), num_bytes_downloaded, num_bytes_downloaded))
project._db.commit()
except Exception as e:
if is_no_such_table_error_for('statistics', e):
# Fail silently if statistics table does not exist
pass
elif is_database_closed_error(e):
# Probably the project was closed. Ignore error.
pass
else:
raise
fg_call_later(fg_task)

# === Utility ===

def __repr__(self) -> str:
return "<ResourceRevision %s for '%s'>" % (self._id, self.resource.url)

Expand Down
7 changes: 7 additions & 0 deletions src/crystal/util/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ def is_no_such_column_error_for(column_name: str, e: Exception) -> bool:
)


def is_no_such_table_error_for(table_name: str, e: Exception) -> bool:
return (
isinstance(e, sqlite3.OperationalError) and
str(e) == f'no such table: {table_name}'
)


def get_index_names(c: DatabaseCursor) -> list[str]:
return [
index_name
Expand Down

0 comments on commit 267cf51

Please sign in to comment.