This commit is contained in:
Timothy Jaeryang Baek
2026-03-22 05:48:05 -05:00
parent 7ffcd3908e
commit ee901fcd2c
2 changed files with 57 additions and 48 deletions
+14 -5
View File
@@ -82,13 +82,22 @@ class RedisDict:
return [(k, json.loads(v)) for k, v in self.redis.hgetall(self.name).items()]
def set(self, mapping: dict):
pipe = self.redis.pipeline()
if not mapping:
self.redis.delete(self.name)
return
pipe.delete(self.name)
if mapping:
pipe.hset(self.name, mapping={k: json.dumps(v) for k, v in mapping.items()})
# Fetch existing keys before writing so we know which ones to remove.
# HKEYS is cheap — it transfers only short key strings, not large JSON values.
existing_keys = set(self.redis.hkeys(self.name))
new_keys = set(mapping.keys())
keys_to_remove = existing_keys - new_keys
pipe.execute()
# HSET first (add/update all new values), then HDEL (remove stale keys).
# We never DELETE the whole hash — this eliminates the race window
# where concurrent readers would see an empty models dict.
self.redis.hset(self.name, mapping={k: json.dumps(v) for k, v in mapping.items()})
if keys_to_remove:
self.redis.hdel(self.name, *keys_to_remove)
def get(self, key, default=None):
try:
@@ -237,49 +237,49 @@
{#if role === 'admin'}
<a
href="/playground"
draggable="false"
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
on:click={async (e) => {
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) {
return;
}
e.preventDefault();
show = false;
goto('/playground');
if ($mobile) {
await tick();
showSidebar.set(false);
}
}}
>
<div class=" self-center mr-3">
<Code className="size-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Playground')}</div>
</a>
<a
href="/admin"
draggable="false"
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
on:click={async (e) => {
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) {
return;
}
e.preventDefault();
show = false;
goto('/admin');
if ($mobile) {
await tick();
showSidebar.set(false);
}
}}
>
<div class=" self-center mr-3">
<UserGroup className="w-5 h-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Admin Panel')}</div>
</a>
href="/playground"
draggable="false"
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
on:click={async (e) => {
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) {
return;
}
e.preventDefault();
show = false;
goto('/playground');
if ($mobile) {
await tick();
showSidebar.set(false);
}
}}
>
<div class=" self-center mr-3">
<Code className="size-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Playground')}</div>
</a>
<a
href="/admin"
draggable="false"
class="flex rounded-xl py-1.5 px-3 w-full hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer select-none"
on:click={async (e) => {
if (e.metaKey || e.ctrlKey || e.shiftKey || e.button === 1) {
return;
}
e.preventDefault();
show = false;
goto('/admin');
if ($mobile) {
await tick();
showSidebar.set(false);
}
}}
>
<div class=" self-center mr-3">
<UserGroup className="w-5 h-5" strokeWidth="1.5" />
</div>
<div class=" self-center truncate">{$i18n.t('Admin Panel')}</div>
</a>
{/if}
{#if help}