Skip to content

Commit de30a4e

Browse files
committed
Limit updates of list to disk to every 5s
1 parent b93b50a commit de30a4e

File tree

1 file changed

+34
-16
lines changed

1 file changed

+34
-16
lines changed

server.py

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import maxminddb
1010
from flask import Flask, request, send_from_directory, make_response
1111

12+
LIST_SAVE_INTERVAL = 5
1213

1314
app = Flask(__name__, static_url_path = "")
1415

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

8081

8182
@app.route("/geoip")
@@ -607,10 +608,10 @@ def __init__(self):
607608
self.maxClients = 0
608609
self.storagePath = os.path.join(app.root_path, "store.json")
609610
self.publicPath = os.path.join(app.static_folder, "list.json")
611+
self.modified = True
610612
self.lock = RLock()
611613

612614
self.load()
613-
self.purgeOld()
614615

615616
def getWithIndex(self, ip, port):
616617
with self.lock:
@@ -636,17 +637,15 @@ def remove(self, server):
636637
self.list.remove(server)
637638
except ValueError:
638639
return
639-
self.save()
640-
self.savePublic()
640+
self.modified = True
641641

642642
def purgeOld(self):
643643
cutoff = int(time.time()) - app.config["PURGE_TIME"]
644644
with self.lock:
645645
count = len(self.list)
646646
self.list = [server for server in self.list if cutoff <= server.updateTime]
647647
if len(self.list) < count:
648-
self.save()
649-
self.savePublic()
648+
self.modified = True
650649

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

666+
# rewrite once in case writing format or so changed
667+
self.modified = True
668+
667669
def save(self):
668670
with self.lock:
671+
self._saveStorage()
672+
self._savePublic()
673+
self.modified = False
674+
675+
def _saveStorage(self):
676+
with self.lock:
677+
if not self.modified:
678+
return
679+
669680
out_list = list(server.to_storage() for server in self.list)
670681
dumpJsonToFile(self.storagePath, {
671682
"list": out_list,
672683
"maxServers": self.maxServers,
673684
"maxClients": self.maxClients
674685
})
675686

676-
def savePublic(self):
687+
def _savePublic(self):
677688
with self.lock:
689+
if not self.modified and os.path.exists(self.publicPath):
690+
return
691+
678692
# sort, but don't modify internal list
679693
sorted_list = sorted(self.list,
680694
key=(lambda server: server.get_score()), reverse=True)
@@ -702,9 +716,7 @@ def update(self, server):
702716
self.list[i] = server
703717
else:
704718
self.list.append(server)
705-
706-
self.save()
707-
self.savePublic()
719+
self.modified = True
708720

709721

710722
class ErrorTracker:
@@ -735,14 +747,20 @@ def cleanup(self):
735747
self.table = table
736748

737749

738-
class PurgeThread(Thread):
750+
class TimerThread(Thread):
739751
def __init__(self):
740-
Thread.__init__(self, daemon=True)
752+
super().__init__(name="TimerThread", daemon=True)
741753
def run(self):
754+
next_cleanup = 0
742755
while True:
743-
time.sleep(60)
744-
serverList.purgeOld()
745-
errorTracker.cleanup()
756+
time.sleep(max(1, LIST_SAVE_INTERVAL))
757+
758+
if time.monotonic() >= next_cleanup:
759+
serverList.purgeOld()
760+
errorTracker.cleanup()
761+
next_cleanup = time.monotonic() + 60
762+
763+
serverList.save()
746764

747765

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

752770
errorTracker = ErrorTracker()
753771

754-
PurgeThread().start()
772+
TimerThread().start()
755773

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

0 commit comments

Comments
 (0)