S
Solara•13mo ago
taltimes2

Aren't all these the responsibility of the browser to fetch stuff from the CDN?

Good afternoon! Can Solara run on a read-only file system? I tried running it on AWS Lambda and it crashed here: https://github.com/widgetti/solara/blob/master/solara/server/settings.py#L159C4-L159C4
GitHub
solara/solara/server/settings.py at master · widgetti/solara
A Pure Python, React-style Framework for Scaling Your Jupyter and Web Apps - widgetti/solara
17 Replies
taltimes2
taltimes2•13mo ago
What if there are 2 instances of the server? Or 20? Where is this directory? What if the server is containerized?
MaartenBreddels
MaartenBreddels•13mo ago
I just had the same issue, and I have a fix locally, really a coincidence you hit the same 🙂 yes, you can turn off the cdn proxy, for that purpose I'll push a fix with documentation on this soon you could open an issue if you want to track it
taltimes2
taltimes2•13mo ago
awesome! Is it a small patch I can apply tonight?
MaartenBreddels
MaartenBreddels•13mo ago
yeah
diff --git a/solara/server/settings.py b/solara/server/settings.py
index fdcbd3d..046f7a7 100644
--- a/solara/server/settings.py
+++ b/solara/server/settings.py
@@ -152,7 +152,12 @@ assets = Assets()
oauth = OAuth()
session = Session()

-assets.proxy_cache_dir.mkdir(exist_ok=True, parents=True)
+try:
+ assets.proxy_cache_dir.mkdir(exist_ok=True, parents=True)
+except PermissionError:
+ # that's ok, the user probably doesn't have permission to create the directory
+ # in this case, we would need to install solara-assets?
+ pass

if telemetry.server_user_id == "not_set":
home = get_solara_home()
diff --git a/solara/server/starlette.py b/solara/server/starlette.py
index e12fa69..ea61198 100644
--- a/solara/server/starlette.py
+++ b/solara/server/starlette.py
@@ -381,7 +381,7 @@ routes = [
Route("/", endpoint=root),
Route("/{fullpath}", endpoint=root),
Route("/_solara/api/close/{connection_id}", endpoint=close, methods=["POST"]),
- Mount(f"/{cdn_url_path}", app=StaticCdn(directory=settings.assets.proxy_cache_dir)),
+ *([Mount(f"/{cdn_url_path}", app=StaticCdn(directory=settings.assets.proxy_cache_dir))] if settings.assets.proxy_cache_dir.exists() else []),
Mount(f"{prefix}/static/public", app=StaticPublic()),
Mount(f"{prefix}/static/assets", app=StaticAssets()),
Mount(f"{prefix}/static/nbextensions", app=StaticNbFiles()),
diff --git a/solara/server/settings.py b/solara/server/settings.py
index fdcbd3d..046f7a7 100644
--- a/solara/server/settings.py
+++ b/solara/server/settings.py
@@ -152,7 +152,12 @@ assets = Assets()
oauth = OAuth()
session = Session()

-assets.proxy_cache_dir.mkdir(exist_ok=True, parents=True)
+try:
+ assets.proxy_cache_dir.mkdir(exist_ok=True, parents=True)
+except PermissionError:
+ # that's ok, the user probably doesn't have permission to create the directory
+ # in this case, we would need to install solara-assets?
+ pass

if telemetry.server_user_id == "not_set":
home = get_solara_home()
diff --git a/solara/server/starlette.py b/solara/server/starlette.py
index e12fa69..ea61198 100644
--- a/solara/server/starlette.py
+++ b/solara/server/starlette.py
@@ -381,7 +381,7 @@ routes = [
Route("/", endpoint=root),
Route("/{fullpath}", endpoint=root),
Route("/_solara/api/close/{connection_id}", endpoint=close, methods=["POST"]),
- Mount(f"/{cdn_url_path}", app=StaticCdn(directory=settings.assets.proxy_cache_dir)),
+ *([Mount(f"/{cdn_url_path}", app=StaticCdn(directory=settings.assets.proxy_cache_dir))] if settings.assets.proxy_cache_dir.exists() else []),
Mount(f"{prefix}/static/public", app=StaticPublic()),
Mount(f"{prefix}/static/assets", app=StaticAssets()),
Mount(f"{prefix}/static/nbextensions", app=StaticNbFiles()),
and use export SOLARA_ASSETS_PROXY=False this is my local diff, i want to do it slightly differently when we detect we cannot write, to give a warning to tell what is going on, and then we automatically turn off the proxy, so it works out of the box
taltimes2
taltimes2•13mo ago
cool thanks! btw - I had an OSError and not a PermissionError - you can create a tuple of exceptions 2023-07-17T12:36:56.731+00:00 [ERROR] OSError: [Errno 30] Read-only file system: '/var/lang/share/solara'
MaartenBreddels
MaartenBreddels•13mo ago
oh, thank you, that's helpful, i'll add that
taltimes2
taltimes2•13mo ago
Can you please let us know when you push the fix?
MaartenBreddels
MaartenBreddels•13mo ago
do you want to review this? https://github.com/widgetti/solara/pull/211 and maybe test it?
GitHub
feat: when the proxy cache dir cannot be written to, disable the pr...
This will let solara work out of the box when the proxy cache dir is not writable, and will not require the user to manually disable the proxy. If the proxy is disabled, the cache dir will not be c...
taltimes2
taltimes2•13mo ago
except Exception as e: ? 🥲 do I still need to set an environment variable?
MaartenBreddels
MaartenBreddels•13mo ago
you don't like us catching all exception? 🙂 at least we're not catching BaseException 🙂 but, given that you had an OSError, and I had a PermissionError, i guess there are more we don't know about you wouldn't need to set an envirioment variable, you will get a warning though
taltimes2
taltimes2•13mo ago
sure, but the way to catch them is by NOT specifying them until they happen... testing now
MaartenBreddels
MaartenBreddels•13mo ago
i'm not sure i follow you, can you elaborate, feel free to use github as well if you prefer that happy to learn here 🙂
taltimes2
taltimes2•13mo ago
I'm not afraid of exceptions - they are informative and the backtrace tells you a lot of the information you need to debug them. except Exception catches even syntax mistakes (!) I would just have used except (OSError, PermissionError) as e and the worst thing that can happen is that you learn about another type of exception in some other system. It's a single line, but it's still Python and a lot of things can go wrong. What if there's no proxy_cache_dir in assets? What if mkdir on some system need different parameters? Doesn't this crash for you: with FileLock(str(server_user_id_file) + ".lock"): (line 172 in settings.py) ?
MaartenBreddels
MaartenBreddels•13mo ago
i agree in general not to catch Exception, but not on trivial lines line this, it's a trade off between catching everything, and not catching enough (especially with files, i've been bitten by not knowing which exceptions are possible) no, my home dir is writable, that also fails for you? what is the exception?
taltimes2
taltimes2•13mo ago
2023-07-18T15:06:59.259+00:00 [ERROR] OSError: [Errno 30] Read-only file system: '/var/task/server_user_id.txt.lock'   File "/var/task/solara/server/settings.py", line 172, in <module>     with FileLock(str(server_user_id_file) + ".lock"):
MaartenBreddels
MaartenBreddels•13mo ago
Python documentation
Built-in Exceptions
In Python, all exceptions must be instances of a class that derives from BaseException. In a try statement with an except clause that mentions a particular class, that clause also handles any excep...
MaartenBreddels
MaartenBreddels•13mo ago
will also fix that error