-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[replit] The lesser of two evils (#167)
* [replit] The lesser of two evils Currently the replit library has a very gross quirk: it has a global in `replit.database.default_db.db`, and the mere action of importing this library causes side effects to run! (connects to the database, starts a thread to refresh the URL, and prints a warning to stdout, adding insult to injury). So we're trading that very gross quirk with a gross workaround to preserve backwards compatibility: the modules that somehow end up importing that module now have a `__getattr__` that _lazily_ calls the code that used to be invoked as a side-effect of importing the library. Maybe in the future we'll deploy a breaking version of the library where we're not beholden to this backwards-compatibility quirck. * Marking internal properties as private Providing accessors, to hint that we are accessing mutable state * Reintroduce refresh_db noop to avoid errors on upgrade * Reflow LazyDB back down into default_db module An issue with LazyDB is that the refresh_db timer would not get canceled if the user closes the database. Additionally, the db_url refresh logic relies on injection, whereas the Database should ideally be the thing requesting that information from the environment * Removing stale main.sh --------- Co-authored-by: Devon Stewart <[email protected]>
- Loading branch information
1 parent
2e7528a
commit 5c0ab7a
Showing
8 changed files
with
200 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,41 +1,58 @@ | ||
"""A module containing the default database.""" | ||
from os import environ, path | ||
import threading | ||
from typing import Optional | ||
|
||
import os | ||
import os.path | ||
from typing import Any, Optional | ||
|
||
from .database import Database | ||
|
||
|
||
def get_db_url() -> str: | ||
def get_db_url() -> Optional[str]: | ||
"""Fetches the most up-to-date db url from the Repl environment.""" | ||
# todo look into the security warning ignored below | ||
tmpdir = "/tmp/replitdb" # noqa: S108 | ||
if path.exists(tmpdir): | ||
if os.path.exists(tmpdir): | ||
with open(tmpdir, "r") as file: | ||
db_url = file.read() | ||
else: | ||
db_url = environ.get("REPLIT_DB_URL") | ||
return file.read() | ||
|
||
return db_url | ||
return os.environ.get("REPLIT_DB_URL") | ||
|
||
|
||
def refresh_db() -> None: | ||
"""Refresh the DB URL every hour.""" | ||
global db | ||
"""Deprecated: refresh_db is now the responsibility of the Database instance.""" | ||
pass | ||
|
||
|
||
def _unbind() -> None: | ||
global _db | ||
_db = None | ||
|
||
|
||
def _get_db() -> Optional[Database]: | ||
global _db | ||
if _db is not None: | ||
return _db | ||
|
||
db_url = get_db_url() | ||
db.update_db_url(db_url) | ||
threading.Timer(3600, refresh_db).start() | ||
|
||
if db_url: | ||
_db = Database(db_url, get_db_url=get_db_url, unbind=_unbind) | ||
else: | ||
# The user will see errors if they try to use the database. | ||
print("Warning: error initializing database. Replit DB is not configured.") | ||
_db = None | ||
return _db | ||
|
||
|
||
_db: Optional[Database] = None | ||
|
||
db: Optional[Database] | ||
db_url = get_db_url() | ||
if db_url: | ||
db = Database(db_url) | ||
else: | ||
# The user will see errors if they try to use the database. | ||
print("Warning: error initializing database. Replit DB is not configured.") | ||
db = None | ||
|
||
if db: | ||
refresh_db() | ||
# Previous versions of this library would just have side-effects and always set | ||
# up a database unconditionally. That is very undesirable, so instead of doing | ||
# that, we are using this egregious hack to get the database / database URL | ||
# lazily. | ||
def __getattr__(name: str) -> Any: | ||
if name == "db": | ||
return _get_db() | ||
if name == "db_url": | ||
return get_db_url() | ||
raise AttributeError(name) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.