Răsfoiți Sursa

feat: 归档启用redis缓存机制

SongZihuan 2 ani în urmă
părinte
comite
56c7ce4198
7 a modificat fișierele cu 109 adăugiri și 25 ștergeri
  1. 1 1
      app/archive.py
  2. 5 4
      app/docx.py
  3. 10 1
      object/archive.py
  4. 30 9
      sql/archive.py
  5. 3 1
      sql/blog.py
  6. 52 1
      sql/cache.py
  7. 8 8
      templates/archive/archive.html

+ 1 - 1
app/archive.py

@@ -22,7 +22,7 @@ class CreateArchiveForm(FlaskForm):
         name = field.data
         archive_list = Archive.get_archive_list()
         for i in archive_list:
-            if name == i[1]:
+            if name == i.name:
                 raise ValidationError("归档已经存在")
 
 

+ 5 - 4
app/docx.py

@@ -36,8 +36,8 @@ class WriteBlogForm(EditorMD):
         self.archive_res = []
         self.archive_choices = [(-1, "None")]
         for i in archive:
-            self.archive_res.append(i[0])
-            self.archive_choices.append((i[0], f"{i[1]} ({i[3]})"))
+            self.archive_res.append(i.id)
+            self.archive_choices.append((i.id, f"{i.name} ({i.count})"))
         self.archive.choices = self.archive_choices
 
     def validate_archive(self, field):
@@ -73,8 +73,9 @@ class UpdateBlogArchiveForm(FlaskForm):
         self.archive_res = []
         self.archive_choices = []
         for i in archive:
-            self.archive_res.append(i[0])
-            self.archive_choices.append((i[0], f"{i[1]} ({i[3]})"))
+            archive_id = i.id
+            self.archive_res.append(archive_id)
+            self.archive_choices.append((archive_id, f"{i.name} ({i.count})"))
         self.archive.choices = self.archive_choices
         if blog is not None:
             self.archive_data = []

+ 10 - 1
object/archive.py

@@ -1,5 +1,6 @@
 from collections import namedtuple
 
+import sql.blog  # 不用 from import 避免循环导入
 from sql.archive import (read_archive,
                          create_archive,
                          get_archive_list,
@@ -14,7 +15,11 @@ class _Archive:
 
     @staticmethod
     def get_archive_list():
-        return get_archive_list()
+        ret = []
+        for i in get_archive_list():
+            ret.append(Archive(i))
+        return ret
+
 
     @staticmethod
     def get_blog_archive(blog_id: int):
@@ -47,6 +52,10 @@ class Archive(_Archive):
     def describe(self):
         return self.info.describe
 
+    @property
+    def count(self):
+        return sql.blog.get_archive_blog_count(self.id)
+
     def is_delete(self):
         return len(self.name) != 0
 

+ 30 - 9
sql/archive.py

@@ -1,4 +1,7 @@
 from sql import db
+from sql.cache import (read_archive_from_cache, write_archive_to_cache, delete_archive_from_cache,
+                       get_blog_archive_from_cache, write_blog_archive_to_cache, delete_blog_archive_from_cache,
+                       delete_all_blog_archive_from_cache)
 from typing import Optional
 
 
@@ -15,25 +18,41 @@ def create_archive(name: str, describe: str):
 
 def read_archive(archive_id: int):
     """ 获取归档 ID """
+    res = read_archive_from_cache(archive_id)
+    if res is not None:
+        return res
+
     cur = db.search("SELECT Name, DescribeText "
                     "FROM archive "
                     "WHERE ID=%s", archive_id)
     if cur is None or cur.rowcount == 0:
         return ["", ""]
-    return cur.fetchone()
+
+    res = cur.fetchone()
+    write_archive_to_cache(archive_id, *res)
+    return res
 
 
 def get_blog_archive(blog_id: int):
     """ 获取文章的归档 """
+    res = get_blog_archive_from_cache(blog_id)
+    if res is not None:
+        return res
+
     cur = db.search("SELECT ArchiveID FROM blog_archive_with_name "
                     "WHERE BlogID=%s "
                     "ORDER BY ArchiveName", blog_id)
     if cur is None or cur.rowcount == 0:
         return []
-    return [i[0] for i in cur.fetchall()]
+
+    res = [i[0] for i in cur.fetchall()]
+    write_blog_archive_to_cache(blog_id, res)
+    return res
 
 
 def delete_archive(archive_id: int):
+    delete_archive_from_cache(archive_id)
+    delete_all_blog_archive_from_cache()
     cur = db.delete("DELETE FROM blog_archive WHERE ArchiveID=%s", archive_id)
     if cur is None:
         return False
@@ -44,6 +63,7 @@ def delete_archive(archive_id: int):
 
 
 def add_blog_to_archive(blog_id: int, archive_id: int):
+    delete_blog_archive_from_cache(blog_id)
     cur = db.search("SELECT BlogID FROM blog_archive WHERE BlogID=%s AND ArchiveID=%s", blog_id, archive_id)
     if cur is None:
         return False
@@ -56,6 +76,7 @@ def add_blog_to_archive(blog_id: int, archive_id: int):
 
 
 def sub_blog_from_archive(blog_id: int, archive_id: int):
+    delete_blog_archive_from_cache(blog_id)
     cur = db.delete("DELETE FROM blog_archive WHERE BlogID=%s AND ArchiveID=%s", blog_id, archive_id)
     if cur is None:
         return False
@@ -65,16 +86,16 @@ def sub_blog_from_archive(blog_id: int, archive_id: int):
 def get_archive_list(limit: Optional[int] = None, offset: Optional[int] = None):
     """ 获取归档列表 """
     if limit is not None and offset is not None:
-        cur = db.search("SELECT ID, Name, DescribeText, Count "
-                        "FROM archive_with_count "
-                        "ORDER BY Count DESC , Name "
+        cur = db.search("SELECT ID "
+                        "FROM archive "  # TODO: 去除 archive_with_count
+                        "ORDER BY Name "
                         "LIMIT %s "
                         "OFFSET %s ", limit, offset)
     else:
-        cur = db.search("SELECT ID, Name, DescribeText, Count "
-                        "FROM archive_with_count "
-                        "ORDER BY Count DESC , Name")
+        cur = db.search("SELECT ID "
+                        "FROM archive "
+                        "ORDER BY Name")
 
     if cur is None or cur.rowcount == 0:
         return []
-    return cur.fetchall()
+    return [i[0] for i in cur.fetchall()]

+ 3 - 1
sql/blog.py

@@ -5,7 +5,8 @@ from sql.cache import (write_blog_to_cache, read_blog_from_cache, delete_blog_fr
                        write_archive_blog_count_to_cache, get_archive_blog_count_from_cache,
                        delete_all_archive_blog_count_from_cache, delete_archive_blog_count_from_cache,
                        write_user_blog_count_to_cache, get_user_blog_count_from_cache,
-                       delete_all_user_blog_count_from_cache, delete_user_blog_count_from_cache)
+                       delete_all_user_blog_count_from_cache, delete_user_blog_count_from_cache,
+                       delete_blog_archive_from_cache)
 import object.archive
 
 
@@ -70,6 +71,7 @@ def delete_blog(blog_id: int):
     delete_all_archive_blog_count_from_cache()
     delete_all_user_blog_count_from_cache()
     delete_blog_from_cache(blog_id)
+    delete_blog_archive_from_cache(blog_id)
 
     cur = db.delete("DELETE FROM blog_archive WHERE BlogID=%s", blog_id)
     if cur is None:

+ 52 - 1
sql/cache.py

@@ -91,7 +91,7 @@ def delete_all_user_msg_count_from_cache():
 @__try_redis(None)
 def read_blog_from_cache(blog_id: int):
     blog = cache.hgetall(f"cache:blog:{blog_id}")
-    if len(blog) != 4:
+    if len(blog) != 7:
         return None
     return [int(blog.get("Auth", -1)),
             blog.get("Title"),
@@ -194,3 +194,54 @@ def delete_all_user_blog_count_from_cache():
 @__try_redis(None)
 def delete_user_blog_count_from_cache(user_id: int):
     cache.delete(f"cache:blog_count:user:{user_id}")
+
+
+@__try_redis(None)
+def read_archive_from_cache(archive_id: int):
+    archive = cache.hgetall(f"cache:archive:{archive_id}")
+    if len(archive) != 2:
+        return None
+    return [archive.get("Name", ""), archive.get("DescribeText")]
+
+
+@__try_redis(None)
+def write_archive_to_cache(archive_id: int, name: str, describe: str):
+    cache_name = f"cache:archive:{archive_id}"
+    cache.delete(cache_name)
+    cache.hset(cache_name, mapping={
+        "Name": name,
+        "DescribeText": describe,
+    })
+    cache.expire(cache_name, 3600)
+
+
+@__try_redis(None)
+def delete_archive_from_cache(archive_id: int):
+    cache.delete(f"cache:archive:{archive_id}")
+
+
+@__try_redis(None)
+def get_blog_archive_from_cache(blog_id: int):
+    blog_archive = cache.lrange(f"cache:blog_archive:{blog_id}", 0, -1)
+    if len(blog_archive) == 0:
+        return None
+    return blog_archive
+
+
+@__try_redis(None)
+def write_blog_archive_to_cache(blog_id: int, archive):
+    cache_name = f"cache:blog_archive:{blog_id}"
+    cache.delete(cache_name)
+    cache.rpush(cache_name, *archive)
+    cache.expire(cache_name, 3600)
+
+
+@__try_redis(None)
+def delete_blog_archive_from_cache(blog_id: int):
+    cache.delete(f"cache:blog_archive:{blog_id}")
+
+
+@__try_redis(None)
+def delete_all_blog_archive_from_cache():
+    for i in cache.keys("cache:blog_archive:*"):
+        cache.delete(i)

+ 8 - 8
templates/archive/archive.html

@@ -50,24 +50,24 @@
     <section id="base" class="d-flex mt-3 container justify-content-center flex-wrap">
         {% for archive in archive_list %}
             <div class="archive mb-3 mx-2">
-                <h3> {{ archive[1] }} </h3>
+                <h3> {{ archive.name }} </h3>
                 <hr>
-                <p class="archive_describe"> {{ archive[2] }} </p>
-                <p> 篇数: {{ archive[3] }} </p>
-                <a class="btn btn-primary" href="{{ url_for("docx.archive_page", archive=archive[0], page=1) }}"> 进入 </a>
+                <p class="archive_describe"> {{ archive.describe }} </p>
+                <p> 篇数: {{ archive.count }} </p>
+                <a class="btn btn-primary" href="{{ url_for("docx.archive_page", archive=archive.id, page=1) }}"> 进入 </a>
                 {% if show_delete %}
-                    <div id="DeleteModal{{archive[0]}}" class="modal fade" role="dialog" aria-hidden="true">
+                    <div id="DeleteModal{{archive.id}}" class="modal fade" role="dialog" aria-hidden="true">
                         <div class="modal-dialog">
                             <div class="modal-content text-start">
                                 <div class="modal-header">
                                     <h4 class="modal-title"> 确认删除归档? </h4>
                                 </div>
                                 <div class="modal-body">
-                                    <p> 是否确认删除归档 {{ archive[1] }}? </p>
+                                    <p> 是否确认删除归档 {{ archive.name }}? </p>
                                 </div>
                                 <div class="modal-footer">
                                     <a class="btn btn-danger"
-                                       href="{{ url_for("archive.delete_archive_page", archive=archive[0]) }}"> 删除 </a>
+                                       href="{{ url_for("archive.delete_archive_page", archive=archive.id) }}"> 删除 </a>
                                     <button type="button" class="btn btn-outline-dark" data-bs-dismiss="modal"> 取消 </button>
                                 </div>
                             </div>
@@ -75,7 +75,7 @@
                     </div>
 
                     <button type="button" class="btn btn-danger"
-                            data-bs-toggle="modal" data-bs-target="#DeleteModal{{archive[0]}}"> 删除归档 </button>
+                            data-bs-toggle="modal" data-bs-target="#DeleteModal{{archive.id}}"> 删除归档 </button>
                 {% endif %}
             </div>
         {% endfor %}