Skip to content

feat(levels): add levels leaderboard #406

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
124 changes: 78 additions & 46 deletions src/common/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# lib imports
import git
from tinydb import TinyDB
from tinydb import TinyDB, Query
from tinydb.storages import JSONStorage
from tinydb.middlewares import CachingMiddleware

Expand All @@ -17,6 +17,7 @@

# Constants
DATA_REPO_LOCK = threading.Lock()
GIT_ENABLED = True # disable to pause pushing to git, useful for heavy db operations


class Database:
Expand Down Expand Up @@ -274,50 +275,81 @@
return self.tinydb

def __exit__(self, exc_type, exc_val, exc_tb):
self.sync()
self.lock.release()
try:
self.sync()
finally:
self.lock.release()

def sync(self):
# Only call flush if using CachingMiddleware
if hasattr(self.tinydb.storage, 'flush'):
self.tinydb.storage.flush()

# Git operations - commit and push changes if using git
with DATA_REPO_LOCK:
if self.use_git and self.repo is not None:
try:
# Check for untracked database files and tracked files with changes
status = self.repo.git.status('--porcelain')

# If there are any changes or untracked files
if status:
# Add ALL json files in the directory to ensure we track all databases
json_files = [f for f in os.listdir(self.db_dir) if f.endswith('.json')]
if json_files:
for json_file in json_files:
file_path = os.path.join(self.db_dir, json_file)
self.repo.git.add(file_path)

# Check if we have anything to commit after adding
if self.repo.git.status('--porcelain'):
# Ensure the repository is configured with user identity
self._configure_repo()

# Commit all changes at once with a general message
commit_message = "Update database files"
self.repo.git.commit('-m', commit_message)
print("Committed changes to git data repository")

# Push to remote with credentials
try:
# Ensure we're using the credentials for push
protocol, repo_path = self.repo_url.split("://", 1)
push_url = f"{protocol}://{self.git_user_name}:{self.git_token}@{repo_path}"
self.repo.git.push(push_url, self.repo_branch)
print("Pushed changes to remote git data repository")
except git.exc.GitCommandError as e:
print(f"Failed to push changes: {str(e)}")

except Exception as e:
print(f"Git operation failed: {str(e)}")
traceback.print_exc()
try:
# Flush changes to disk if possible
if self.tinydb and hasattr(self.tinydb.storage, 'flush'):
self.tinydb.storage.flush()

# Close the database to ensure file is available for Git operations
if self.tinydb is not None:
self.tinydb.close()
self.tinydb = None

# Git operations with closed file
with DATA_REPO_LOCK:
if self.use_git and self.repo is not None and GIT_ENABLED:
try:

Check warning on line 297 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L297

Added line #L297 was not covered by tests
# Check for untracked database files and tracked files with changes
status = self.repo.git.status('--porcelain')

Check warning on line 299 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L299

Added line #L299 was not covered by tests

# If there are any changes or untracked files
if status:

Check warning on line 302 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L302

Added line #L302 was not covered by tests
# Add ALL json files in the directory to ensure we track all databases
json_files = [f for f in os.listdir(self.db_dir) if f.endswith('.json')]
if json_files:
for json_file in json_files:
file_path = os.path.join(self.db_dir, json_file)
self.repo.git.add(file_path)

Check warning on line 308 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L304-L308

Added lines #L304 - L308 were not covered by tests

# Check if we have anything to commit after adding
if self.repo.git.status('--porcelain'):

Check warning on line 311 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L311

Added line #L311 was not covered by tests
# Ensure the repository is configured with user identity
self._configure_repo()

Check warning on line 313 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L313

Added line #L313 was not covered by tests

# Commit all changes at once with a general message
commit_message = "Update database files"
self.repo.git.commit('-m', commit_message)
print("Committed changes to git data repository")

Check warning on line 318 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L316-L318

Added lines #L316 - L318 were not covered by tests

# Push to remote with credentials
try:

Check warning on line 321 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L321

Added line #L321 was not covered by tests
# Ensure we're using the credentials for push
protocol, repo_path = self.repo_url.split("://", 1)
push_url = f"{protocol}://{self.git_user_name}:{self.git_token}@{repo_path}"
self.repo.git.push(push_url, self.repo_branch)
print("Pushed changes to remote git data repository")
except git.exc.GitCommandError as e:
print(f"Failed to push changes: {str(e)}")

Check warning on line 328 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L323-L328

Added lines #L323 - L328 were not covered by tests

except Exception as e:
print(f"Git operation failed: {str(e)}")
traceback.print_exc()

Check warning on line 332 in src/common/database.py

View check run for this annotation

Codecov / codecov/patch

src/common/database.py#L330-L332

Added lines #L330 - L332 were not covered by tests
finally:
# Ensure database is ready for next use
if self.tinydb is None:
self.tinydb = TinyDB(
self.json_path,
storage=CachingMiddleware(JSONStorage),
indent=4,
)

@staticmethod
def query():
"""
Get the TinyDB Query object for constructing database queries.

This is a helper method to avoid importing the Query class directly
in modules that use the Database class.

Returns
-------
Query
A TinyDB Query object for constructing queries.
"""
return Query()
Loading
Loading