I've encountered a peculiar scenario while working on a CherryPy server, and I'm seeking assistance in understanding the intricacies behind it. Here's the content of server.py
:
import cherrypy
import os
import threading
class Root(object):
def __init__(self):
self.count = 0;
self.lock = threading.Lock()
@cherrypy.expose
def app(self):
with self.lock:
self.count += 1
return "Call #%d" % (self.count)
if __name__ == '__main__':
cherrypy.quickstart(Root(), "/", {"/": { "tools.staticdir.on": True,
"tools.staticdir.dir": os.getcwd() } })
This is a simple application containing some state managed by a mutex. Now, let's take a look at index.html
:
<!doctype html>
<script src=http://code.jquery.com/jquery-1.8.2.js></script>
<script src=index.js></script>
(The minimal HTML structure aligns with ideas from this talk by Paul Irish). Moving on to index.js
:
function request() {
var cb = function (response) {
console.log(response);
};
$.ajax({
url: "/app",
success: cb
});
}
function go_slow(N, delay) {
if (N > 0) {
request();
window.setTimeout(go_slow, delay, N - 1, delay);
}
}
function go_fast(N) {
var i;
for (i = 0; i < N; i++) {
request();
}
}
window.onload = function () {
//go_slow(100, 0);
go_fast(100);
};
All these files should be placed within the same directory. When launching the CherryPy server and accessing http://localhost:8080/index.html
, multiple instances of "Call #1" appear in the console, while the CherryPy log indicates only one GET request to "/app". Interestingly, Firefox reveals expected behavior compared to Chrome.
If the go_fast()
method is swapped with go_slow()
, which uses 'trampolining' logic to manipulate ajax requests individually over time, the "#1" through "#100" output can be observed on both browsers.
By altering the app()
method in the server to accept but ignore an argument:
@cherrypy.expose
def app(self, i):
with self.lock:
self.count += 1
return "Call #%d" % (self.count)
and reflecting this change in request()
and go_fast()
:
function request(i) {
var cb = function (response) {
console.log(response);
};
$.ajax({
url: "/app/" + i,
success: cb
});
}
function go_fast(N) {
var i;
for (i = 0; i < N; i++) {
request(i);
}
}
The display reverts back to showing "#1" through "#100" consistently. The caching phenomenon in Chrome puzzles me as only one ajax call reflects in response, thereby repeating "Call #1" multiple times. Firefox behaves differently, emphasizing that "caching" might not be solely responsible.
In varying scenarios, the caching mechanism seems evaded. Trampolining may reset the context of each ajax request, negating potential cache retention. On the other hand, appending a positional argument ensures unique URLs per call, effectively bypassing any caching protocols.
Can someone elucidate what precisely unfolds here? Is this an idiosyncrasy with how Chrome handles rapid fire ajax requests or does it unveil profound issues pertaining to stateful ajax resources?