Skip to content
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

Load Replit DB URL from a file #139

Merged
merged 9 commits into from
Jul 6, 2023

Conversation

brenoafb
Copy link
Contributor

@brenoafb brenoafb commented Apr 7, 2023

Why

The JWT used for authenticating into the Replit DB is placed on the Repl as an environment variable on boot and lasts for 30h or so. This is fine for shorter lasting Repls, but if we want to have long-running Repls we need a mechanism to refresh the DB token.

What changed

Let's make it so that we read the DB URL data from a file, which can be refreshed while a program is running. If the file does not exist or we fail to read from it, fall back to the environment variable. We then run this hourly.

Testing

  • Fork this Repl
  • Change the version of the replit dependency in pyproject.toml to the latest commit in this branch. The resulting [tool.poetry.dependencies] section should look something like the following.
[tool.poetry.dependencies]
python = ">=3.10.0,<3.11"
numpy = "^1.22.2"
Flask = "^2.2.0"
urllib3 = "^1.26.12"
replit = { git = "https://github.com/replit/replit-py.git", rev = "71466f774ef1c0d737259d249085dc42606424cd" }
  • Run poetry update
  • Run the Repl and make sure the application works
  • Deploy the Repl and make sure that it still works. Also check that both the plain Repl and the deployment are using the same database by checking that the values shown on the page match.

Copy link
Contributor Author

brenoafb commented Apr 7, 2023

Current dependencies on/for this PR:

This comment was auto-generated by Graphite.

@brenoafb brenoafb marked this pull request as ready for review April 10, 2023 18:43
@airportyh
Copy link
Contributor

Probably meant poetry update instead of flask update?

"""
global db
global db_url
if path.exists("/tmp/replitdb"):
Copy link
Contributor

@airportyh airportyh May 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't find this file. Is this created exclusively in deployment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct

@@ -16,6 +16,13 @@ async def asyncSetUp(self) -> None:
"""Grab a JWT for all the tests to share."""
if "REPLIT_DB_URL" in os.environ:
self.db = AsyncDatabase(os.environ["REPLIT_DB_URL"])
elif "DB_RIDT" in os.environ:
Copy link
Contributor

@airportyh airportyh May 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this var set exclusively in deployment? Or for testing only?

Copy link
Contributor Author

@brenoafb brenoafb May 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for testing, I found it to be the quickest way to switch between using JWT or Repl Identity for authing into the DB

Copy link
Contributor

@airportyh airportyh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm. Just a couple of questions.

db = Database(db_url)
else:
# The user will see errors if they try to use the database.
db = None
Copy link
Contributor

@airportyh airportyh May 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I missed this. But there's a problem here. The global db being updated will not be updated for callers that are importing it via from default_db import db.

Example counter.py

count = 1

def increment():
    global count
    count += 2

main.py

from counter import count, increment

print(count)
increment()

print(count)

This will print:

1
1

I suggest instead of making updating the db with a new instance, make the database self-reloading. Or have a db that's exported to the users be a proxy object that defers to a read db instance which handles reloading.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch! i think updating the db_url property should work here, let me take a look

Copy link
Contributor Author

@brenoafb brenoafb May 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, I added a update_db_url method to the Database class. Now we initialize the default database and call the method periodically with an up-to-date URL. I tested on an example Repl and it appears to be working fine.

@brenoafb brenoafb requested a review from airportyh May 11, 2023 16:53
Copy link
Contributor

@airportyh airportyh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested with a 10 second period. Works fine after the db refresh.

@PotentialStyx
Copy link
Contributor

Is a timer in a thread really needed? Couldn't the db class just store the time of last url refresh. Then every db operation check if the last refresh was over an hour ago, if so only refresh the url then.

@lafkpages
Copy link

Is this ever gonna get merged? I've seen a few users complaining about no support for Repl DB in deployed Python Repls.

@triviatroy
Copy link

What is the timeline on this update? This is a high priority for me given always-on is unstable now.

@brenoafb
Copy link
Contributor Author

brenoafb commented Jul 3, 2023

Is this ever gonna get merged? I've seen a few users complaining about no support for Repl DB in deployed Python Repls.
What is the timeline on this update? This is a high priority for me given always-on is unstable now.

This fix is already in pypi (version 3.3.0 https://pypi.org/project/replit/). Just run poetry update replit on a Repl and the DB should work on a deployment. Sorry for any inconvenience, if you need further help getting ReplDB to work on deployments just get in touch with support and we'll help you out :)

@PotentialStyx
Copy link
Contributor

This fix is already in pypi (version 3.3.0 https://pypi.org/project/replit/).

Just wondering, but shouldn't this PR be merged then?

@masad-frost masad-frost merged commit cee2529 into master Jul 6, 2023
@masad-frost masad-frost deleted the bb04-07-Load_Replit_DB_URL_from_a_file branch July 6, 2023 14:53
@lafkpages
Copy link

Nice

@blast-hardcheese blast-hardcheese added the enhancement New feature or request label Dec 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants