pretext-cli icon indicating copy to clipboard operation
pretext-cli copied to clipboard

Codespace/codechat issue with 2.3.5+

Open StevenClontz opened this issue 1 year ago • 21 comments

I assume this has something to do with how static files are now handled. But in a Codespace using PreTeXt-CLI 2.3.5 or 2.3.6, CodeChat builds are taking a long, sometimes random amount of time. Downgrading to 2.3.4 alleviates the issue. (EDIT: or maybe not - now I'm having trouble with 2.3.4.)

StevenClontz avatar Jan 31 '24 15:01 StevenClontz

As of today, new projects created with pretext-codespaces do not work with codechat preview.

Temporary workaround is still to pip install pretext==2.3.4

StevenClontz avatar Feb 28 '24 19:02 StevenClontz

So I discovered during my faculty meeting demo of pretext <facepalm />. In fact, it seems like we now have the same issues with pretext view, even after fixing it previously.

Could I have reverted the 2.3.6 fix in 2.3.7???

oscarlevin avatar Feb 28 '24 23:02 oscarlevin

Yeah, it also works fine in 2.3.6. I'm guessing there was a change in the static js files, since this uses a newer core commit. Infact, building with 2.3.8 and viewing with 2.3.6 does not work.

Also, we need to figure out a way to put this in our tests. Not understanding what the issue actually is, I'm not sure how to test for it.

oscarlevin avatar Feb 28 '24 23:02 oscarlevin

I think the correct fix is to package these files in a JS bundler (esbuild is my favorite). Otherwise, we'll keep getting shut down by Microsoft's firewall, which thinks we're using CodeSpaces as a web server.

@siefkenj and of course Brad have lots of experience doing this. Is there any interest from the core team (@rbeezer, etc.) for doing this? If so, this should be done with Runestone in mind, since we already bundle JS using Runestone.

bjones1 avatar Feb 29 '24 16:02 bjones1

This isn't just a Codespaces thing for clarity, though that's the pain at hand today - we need to produce HTML that can be served even if the host rate limits the number of javascript files loaded.

StevenClontz avatar Feb 29 '24 17:02 StevenClontz

Could someone clarify for me exactly what the problem is. (or point me to the discussion on -dev if it is already there.). I'm having a hard time figuring out how build times and rate limits on javascript loads are related...

bnmnetp avatar Feb 29 '24 17:02 bnmnetp

Here is the -dev link: https://groups.google.com/g/pretext-dev/c/VABcbEle0R0

For what it's worth, I don't see the problem when using just a simple python -m http.server command and navigating to the output folder. I have never run into issues with a deployed book. As far as I know, it only shows up inside codespaces.

oscarlevin avatar Feb 29 '24 18:02 oscarlevin

Thanks Oscar, I just found it myself.

Are you seeing a status code of 429 Too many requests in codespaces?

In looking at several pages from the sample book, built with 2.3.8 emacs only counts 22 css or js files that are loaded from _static That does not seem excessive to me. 🤷🏻

Github pages only rate limit is on the overall bandwidth used during the course of a month. A simple github page loads more than 40 js files!

bnmnetp avatar Feb 29 '24 18:02 bnmnetp

Oscar, are you running the simple python based server in codespaces?

Maybe someone should look at the network panel in the browser when using CodeChat to get a sense for how much requesting is going on in the background....

bnmnetp avatar Feb 29 '24 19:02 bnmnetp

CodeChat adds just a few more files that are loaded at startup, then not reloaded. However, it doesn't cache files so that any edits to a page get revealed immediately.

bjones1 avatar Feb 29 '24 19:02 bjones1

If a user is editing pretext and viewing the results in codechat they are not changing the javascript or css... So I'm not seeing the harm in caching the css/js files. Sorry if I'm still not understanding the problem well enough.

I guess I should take some time and try to set up one of my books under codespaces so I can see the user experience.

bnmnetp avatar Feb 29 '24 19:02 bnmnetp

I'm wondering now if it is a permissions issue. Here is one of a bunch of errors I get from the console when a page finally loads:

Refused to execute script from 'https://glorious-space-guide-jgxwgv5rg63v9w-8128.app.github.dev/output/web/_static/pretext/js/pretext_search.js' because its MIME type ('') is not executable, and strict MIME type checking is enabled.

Also a lot of:

pretext_add_on.js:1 Failed to load resource: the server responded with a status of 504 ()

Another odd thing: when I test using the pretext-cli codespace for development, it works just fine. It is only on a pretext project in its own codespace that has issues. Checking permissions of the output folders seems to show no difference though.

Here is some output from the terminal:

127.0.0.1 - - [29/Feb/2024 20:04:26] "GET /output/web/_static/pretext/js/pretext.js HTTP/1.1" 304 -
127.0.0.1 - - [29/Feb/2024 20:04:26] "GET /output/web/_static/pretext/css/shell_default.css HTTP/1.1" 304 -
127.0.0.1 - - [29/Feb/2024 20:04:26] "GET /output/web/_static/pretext/css/pretext.css HTTP/1.1" 200 -
127.0.0.1 - - [29/Feb/2024 20:06:35] "GET /output/web/_static/pretext/css/colors_blue_red.css HTTP/1.1" 304 -
127.0.0.1 - - [29/Feb/2024 20:06:35] "GET /output/web/_static/pretext/css/knowls_default.css HTTP/1.1" 304 -
127.0.0.1 - - [29/Feb/2024 20:06:35] "GET /output/web/generated/latex-image/tikz-cone.svg HTTP/1.1" 200 -
----------------------------------------
Exception occurred during processing of request from ('127.0.0.1', 48400)
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/socketserver.py", line 317, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/local/lib/python3.11/socketserver.py", line 348, in process_request
    self.finish_request(request, client_address)
  File "/usr/local/lib/python3.11/socketserver.py", line 361, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/lib/python3.11/http/server.py", line 671, in __init__
    super().__init__(*args, **kwargs)
  File "/usr/local/lib/python3.11/socketserver.py", line 755, in __init__
    self.handle()
  File "/usr/local/lib/python3.11/http/server.py", line 436, in handle
    self.handle_one_request()
  File "/usr/local/lib/python3.11/http/server.py", line 424, in handle_one_request
    method()
  File "/usr/local/lib/python3.11/http/server.py", line 678, in do_GET
    self.copyfile(f, self.wfile)
  File "/usr/local/lib/python3.11/http/server.py", line 877, in copyfile
    shutil.copyfileobj(source, outputfile)
  File "/usr/local/lib/python3.11/shutil.py", line 200, in copyfileobj
    fdst_write(buf)
  File "/usr/local/lib/python3.11/socketserver.py", line 834, in write
    self._sock.sendall(b)
BrokenPipeError: [Errno 32] Broken pipe
----------------------------------------
127.0.0.1 - - [29/Feb/2024 20:06:37] "GET /output/web/_static/pretext/js/user_preferences.js HTTP/1.1" 200 -
----------------------------------------
Exception occurred during processing of request from ('127.0.0.1', 48430)
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/socketserver.py", line 317, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/local/lib/python3.11/socketserver.py", line 348, in process_request
    self.finish_request(request, client_address)
  File "/usr/local/lib/python3.11/socketserver.py", line 361, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/local/lib/python3.11/http/server.py", line 671, in __init__
    super().__init__(*args, **kwargs)
  File "/usr/local/lib/python3.11/socketserver.py", line 755, in __init__
    self.handle()
  File "/usr/local/lib/python3.11/http/server.py", line 436, in handle
    self.handle_one_request()
  File "/usr/local/lib/python3.11/http/server.py", line 424, in handle_one_request
    method()
  File "/usr/local/lib/python3.11/http/server.py", line 678, in do_GET
    self.copyfile(f, self.wfile)
  File "/usr/local/lib/python3.11/http/server.py", line 877, in copyfile
    shutil.copyfileobj(source, outputfile)
  File "/usr/local/lib/python3.11/shutil.py", line 200, in copyfileobj
    fdst_write(buf)
  File "/usr/local/lib/python3.11/socketserver.py", line 834, in write
    self._sock.sendall(b)
BrokenPipeError: [Errno 32] Broken pipe
----------------------------------------
127.0.0.1 - - [29/Feb/2024 20:06:38] "GET /output/web/_static/pretext/css/pretext_search.css HTTP/1.1" 200 -

oscarlevin avatar Feb 29 '24 20:02 oscarlevin

My guess: the broken pipe occurs because CodeSpaces permanently closed the port due to exceeding rate limits, not because of permissions.

bjones1 avatar Feb 29 '24 20:02 bjones1

If a user is editing pretext and viewing the results in codechat they are not changing the javascript or css... So I'm not seeing the harm in caching the css/js files. Sorry if I'm still not understanding the problem well enough.

Most of the time, the CSS/JS don't change, but if Pretext gets upgraded, it might. Perhaps we can cache these anyway and warn users they need to force a reload? Or do the CSS/JS files have some sort of version specifier to help with this?

bjones1 avatar Feb 29 '24 20:02 bjones1

This:

Refused to execute script from 'https://glorious-space-guide-jgxwgv5rg63v9w-8128.app.github.dev/output/web/_static/pretext/js/pretext_search.js' because its MIME type ('') is not executable, and strict MIME type checking is enabled.

Seems quite significant. Especially since the script tags to the _static assets do not have a type. I know it is supposed to default to javascript but if strict checking is enabled it seems it is refusing to serve it.

Again, using the Network tab might give more clues as far as response codes from the server.

bnmnetp avatar Feb 29 '24 20:02 bnmnetp

In the just released 2.3.9, I found a workaround for now at least (but not for codechat): when the CLI notices that we are using codespaces, it will simply subprocess.run("pretext -m http.server"), which seems to work. I feel very silly calling a python subprocess from a python script, but no variation of the imported http.server module seemed to get me a working system.

oscarlevin avatar Mar 03 '24 02:03 oscarlevin

@oscarlevin The command pretext -m http.server runs the http.server.py module as though __name__ == '__main__' is True To make it work without using subprocess you would need to grab the last 20 lines from server.py and drop them into your code.

bnmnetp avatar Mar 04 '24 15:03 bnmnetp

This:

Refused to execute script from 'https://glorious-space-guide-jgxwgv5rg63v9w-8128.app.github.dev/output/web/_static/pretext/js/pretext_search.js' because its MIME type ('') is not executable, and strict MIME type checking is enabled.

Seems quite significant. Especially since the script tags to the _static assets do not have a type. I know it is supposed to default to javascript but if strict checking is enabled it seems it is refusing to serve it.

Again, using the Network tab might give more clues as far as response codes from the server.

I did some debug on CodeChat -- I only get this when the server doesn't respond to a request, so the client gets no/empty data and therefore sees an empty MIME time. When the server does respond, it sends the correct MIME type.

bjones1 avatar Mar 04 '24 15:03 bjones1

I spent a fair amount of time debugging this weekend. I haven't tracked down the root case. Observations:

  • Throttling the server doesn't help, even slowing to 1 response per 5 seconds.
  • The problem is intermittent. It usually doesn't work, but sometimes does work, with the same code.
  • The client requests data from the server. The server responds to all client requests it receives. But, some requests seem to be dropped routing from the client back to the server.
  • Using python -m http.server always works, with no dropped requests.
  • Using the equivalent Bottle server doesn't work. (I use the bottle.py server for CodeChat.)
  • Reverting to an older version of PreTeXt, in which there are fewer local files to load, always works.
  • Outside the CodeSpaces environment, the server works without problems.

bjones1 avatar Mar 04 '24 16:03 bjones1

I filed https://github.com/bottlepy/bottle/issues/1442, hoping the Bottle team can track this down.

bjones1 avatar Mar 05 '24 23:03 bjones1

I tried switching back to Flask as a server, but that also failed.

bjones1 avatar Mar 06 '24 05:03 bjones1