Skip to content

Commit

Permalink
Limit updates of list to disk to every 5s
Browse files Browse the repository at this point in the history
  • Loading branch information
sfan5 committed Feb 17, 2025
1 parent d28b1e6 commit 777ad8d
Showing 1 changed file with 34 additions and 16 deletions.
50 changes: 34 additions & 16 deletions server.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import maxminddb
from flask import Flask, request, send_from_directory, make_response

LIST_SAVE_INTERVAL = 5

app = Flask(__name__, static_url_path = "")

Expand Down Expand Up @@ -75,7 +76,7 @@ def index():
def list_json():
# We have to make sure that the list isn't cached for too long,
# since it isn't really static.
return send_from_directory(app.static_folder, "list.json", max_age=20)
return send_from_directory(app.static_folder, "list.json", max_age=LIST_SAVE_INTERVAL)


@app.route("/geoip")
Expand Down Expand Up @@ -607,10 +608,10 @@ def __init__(self):
self.maxClients = 0
self.storagePath = os.path.join(app.root_path, "store.json")
self.publicPath = os.path.join(app.static_folder, "list.json")
self.modified = True
self.lock = RLock()

self.load()
self.purgeOld()

def getWithIndex(self, ip, port):
with self.lock:
Expand All @@ -636,17 +637,15 @@ def remove(self, server):
self.list.remove(server)
except ValueError:
return
self.save()
self.savePublic()
self.modified = True

def purgeOld(self):
cutoff = int(time.time()) - app.config["PURGE_TIME"]
with self.lock:
count = len(self.list)
self.list = [server for server in self.list if cutoff <= server.updateTime]
if len(self.list) < count:
self.save()
self.savePublic()
self.modified = True

def load(self):
# TODO?: this is a poor man's database. maybe we should use sqlite3?
Expand All @@ -664,17 +663,32 @@ def load(self):
self.maxServers = data["maxServers"]
self.maxClients = data["maxClients"]

# rewrite it once in case anything changed
self.modified = True

def save(self):
with self.lock:
self._saveStorage()
self._savePublic()
self.modified = False

def _saveStorage(self):
with self.lock:
if not self.modified:
return

out_list = list(server.to_storage() for server in self.list)
dumpJsonToFile(self.storagePath, {
"list": out_list,
"maxServers": self.maxServers,
"maxClients": self.maxClients
})

def savePublic(self):
def _savePublic(self):
with self.lock:
if not self.modified and os.path.exists(self.publicPath):
return

# sort, but don't modify internal list
sorted_list = sorted(self.list,
key=(lambda server: server.get_score()), reverse=True)
Expand Down Expand Up @@ -702,9 +716,7 @@ def update(self, server):
self.list[i] = server
else:
self.list.append(server)

self.save()
self.savePublic()
self.modified = True


class ErrorTracker:
Expand Down Expand Up @@ -735,14 +747,20 @@ def cleanup(self):
self.table = table


class PurgeThread(Thread):
class TimerThread(Thread):
def __init__(self):
Thread.__init__(self, daemon=True)
super().__init__(name="TimerThread", daemon=True)
def run(self):
next_cleanup = 0
while True:
time.sleep(60)
serverList.purgeOld()
errorTracker.cleanup()
time.sleep(max(1, LIST_SAVE_INTERVAL))

if time.monotonic() >= next_cleanup:
serverList.purgeOld()
errorTracker.cleanup()
next_cleanup = time.monotonic() + 60

serverList.save()


# Globals / Startup
Expand All @@ -751,7 +769,7 @@ def run(self):

errorTracker = ErrorTracker()

PurgeThread().start()
TimerThread().start()

if __name__ == "__main__":
app.run(host = app.config["HOST"], port = app.config["PORT"])

0 comments on commit 777ad8d

Please sign in to comment.