From 38ebc629ba231ed57d760ec4793d4f94fda31d64 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Thu, 14 Apr 2022 23:22:31 +0530 Subject: [PATCH 1/5] feat: conditionally load data from DB when updating issues and comments SUMMARY DBIssue and DBComment loaded data from database when performing updates via self.__update() which in some cases where unnecessary as a fetch would have been performed just before invoking __update(). This patch introduces an optical parameter to provide recently loaded data from DB --- interface/db/comments.py | 115 +++++++++++++++++++++++++++++++-------- interface/db/issues.py | 68 ++++++++++++++--------- 2 files changed, 135 insertions(+), 48 deletions(-) diff --git a/interface/db/comments.py b/interface/db/comments.py index 3d4e0b8..bfd6964 100644 --- a/interface/db/comments.py +++ b/interface/db/comments.py @@ -23,6 +23,7 @@ from .issues import DBIssue from .interfaces import DBInterfaces from .cache import RecordCount +from .activity import DBActivity, ActivityType @dataclass @@ -37,6 +38,8 @@ class DBComment: belongs_to_issue: DBIssue count = RecordCount("gitea_issue_comments") + id = None + __belongs_to_issue_id: int = None def __set_sqlite_to_bools(self): @@ -48,28 +51,44 @@ def __set_sqlite_to_bools(self): """ self.is_native = bool(self.is_native) - def __update(self): + def __update(self, from_db: "DBComment" = None): """ Update changes in database Only fields that can be mutated on the forge will be updated in the DB """ - conn = get_db() - cur = conn.cursor() - cur.execute( - """ - UPDATE gitea_issue_comments - SET - body = ?, - updated = ? - WHERE - comment_id = ?; - """, - (self.body, self.updated, self.comment_id), - ) - conn.commit() + comment = from_db + if from_db is None: + comment = self.load_from_id(self.id) + if any([comment.body != self.body, comment.updated != self.updated]): + conn = get_db() + cur = conn.cursor() + cur.execute( + """ + UPDATE gitea_issue_comments + SET + body = ?, + updated = ? + WHERE + comment_id = ?; + """, + (self.body, self.updated, self.comment_id), + ) + conn.commit() + DBActivity( + user_id=self.user.id, + activity=ActivityType.UPDATE, + created=self.updated, + comment_id=self.id, + ).save() def save(self): """Save COmment to database""" + + comment = self.load_from_comment_url(self.html_url) + if comment is not None: + self.id = comment.id + self.__update(from_db=comment) + self.user.save() self.belongs_to_issue.save() @@ -106,13 +125,18 @@ def save(self): conn.commit() data = cur.execute( """ - SELECT ID from gitea_issue_comments WHERE html_url = ? - - """, + SELECT ID from gitea_issue_comments WHERE html_url = ? + """, (self.html_url,), ).fetchone() self.id = data[0] self.__update() + DBActivity( + user_id=self.user.id, + activity=ActivityType.CREATE, + created=self.created, + comment_id=self.id, + ).save() @classmethod def load_from_comment_url(cls, comment_url: str) -> "DBComment": @@ -128,7 +152,8 @@ def load_from_comment_url(cls, comment_url: str) -> "DBComment": updated, comment_id, is_native, - user + user, + ID FROM gitea_issue_comments WHERE @@ -151,6 +176,48 @@ def load_from_comment_url(cls, comment_url: str) -> "DBComment": user=user, belongs_to_issue=belongs_to_issue, ) + comment.id = data[7] + comment.__set_sqlite_to_bools() + return comment + + @classmethod + def load_from_id(cls, db_id: int) -> "DBComment": + """Load comment based on ID assigned by database""" + conn = get_db() + cur = conn.cursor() + data = cur.execute( + """ + SELECT + body, + belongs_to_issue, + created, + updated, + comment_id, + is_native, + user, + html_url + FROM + gitea_issue_comments + WHERE + ID = ? + """, + (db_id,), + ).fetchone() + if data is None: + return None + + user = DBUser.load_with_db_id(data[6]) + belongs_to_issue = DBIssue.load_with_id(data[1]) + comment = cls( + body=data[0], + html_url=data[7], + created=data[2], + updated=data[3], + comment_id=data[4], + is_native=data[5], + user=user, + belongs_to_issue=belongs_to_issue, + ) comment.__set_sqlite_to_bools() return comment @@ -168,7 +235,8 @@ def load_issue_comments(cls, issue: DBIssue) -> "[DBComment]": updated, comment_id, is_native, - user + user, + ID FROM gitea_issue_comments WHERE @@ -182,7 +250,7 @@ def load_issue_comments(cls, issue: DBIssue) -> "[DBComment]": comments = [] for comment in data: user = DBUser.load_with_db_id(comment[6]) - comment = cls( + obj = cls( body=comment[0], html_url=comment[1], created=comment[2], @@ -192,8 +260,9 @@ def load_issue_comments(cls, issue: DBIssue) -> "[DBComment]": user=user, belongs_to_issue=issue, ) - comment.__set_sqlite_to_bools() - comments.append(comment) + obj.id = comment[7] + obj.__set_sqlite_to_bools() + comments.append(obj) if len(comments) == 0: return None diff --git a/interface/db/issues.py b/interface/db/issues.py index f0ecf98..860af97 100644 --- a/interface/db/issues.py +++ b/interface/db/issues.py @@ -125,35 +125,52 @@ def set_open(self, updated: str): self.is_merged = False self.__update() - def __update(self): + def __update(self, from_db: "DBIssue" = None): """ Update changes in database Only fields that can be mutated on the forge will be updated in the DB """ - conn = get_db() - cur = conn.cursor() - cur.execute( - """ - UPDATE gitea_forge_issues - SET - title = ?, - description = ?, - updated = ?, - is_closed = ?, - is_merged = ? - WHERE - id = ? - """, - ( - self.title, - self.description, - self.updated, - self.is_closed, - self.is_merged, - self.id, - ), - ) - conn.commit() + issue = from_db + if from_db is None: + issue = self.load_with_id(db_id=self.id) + if any( + [ + issue.title != self.title, + issue.description != self.description, + issue.is_closed != self.is_closed, + issue.is_merged != self.is_merged, + ] + ): + conn = get_db() + cur = conn.cursor() + cur.execute( + """ + UPDATE gitea_forge_issues + SET + title = ?, + description = ?, + updated = ?, + is_closed = ?, + is_merged = ? + WHERE + id = ? + """, + ( + self.title, + self.description, + self.updated, + self.is_closed, + self.is_merged, + self.id, + ), + ) + conn.commit() + DBActivity( + user_id=self.user.id, + activity=ActivityType.UPDATE, + created=self.updated, + issue_id=self.id, + ).save() def save(self): """Save Issue to database""" @@ -164,6 +181,7 @@ def save(self): self.user = issue.user self.repository = issue.repository self.id = issue.id + self.__update(from_db=issue) return self.user.save() From 46442cca5fd61d07b482707d582f8123d5189869 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Thu, 14 Apr 2022 23:52:12 +0530 Subject: [PATCH 2/5] fix: sort comments based on cration time by default --- interface/db/comments.py | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/db/comments.py b/interface/db/comments.py index bfd6964..27c045c 100644 --- a/interface/db/comments.py +++ b/interface/db/comments.py @@ -241,6 +241,7 @@ def load_issue_comments(cls, issue: DBIssue) -> "[DBComment]": gitea_issue_comments WHERE belongs_to_issue = ? + ORDER BY created """, (issue.id,), ).fetchall() From ab6c56b9a877b8f6a8bc03920d5c9a59070d89b7 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Thu, 14 Apr 2022 23:56:24 +0530 Subject: [PATCH 3/5] fix: set user ID upon DBUser.save() --- interface/db/users.py | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/db/users.py b/interface/db/users.py index 594031b..c4cf1e4 100644 --- a/interface/db/users.py +++ b/interface/db/users.py @@ -76,6 +76,7 @@ def save(self): ), ) conn.commit() + self.id = self.load(self.user_id).id break except IntegrityError as e: count += 1 From 482d9810e1bf5887d76b99420dbf57e196e62987 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Thu, 14 Apr 2022 23:58:11 +0530 Subject: [PATCH 4/5] chore: use helper functions to init test data and rm test instability TEST INSTABILITY db/test_comments test was unstable because data generated were saved at separate locations, resulting in uncontrolled/weird data created and updated time. All test data are now saved with one save call, at the top most data type(DBComment is at a higher level as it wraps over/dependant on DBIssue) --- tests/db/test_comments.py | 128 ++++------------------- tests/db/test_issue.py | 102 ++----------------- tests/db/test_repo.py | 46 +-------- tests/db/test_user.py | 27 +---- tests/db/utils.py | 209 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+), 265 deletions(-) create mode 100644 tests/db/utils.py diff --git a/tests/db/test_comments.py b/tests/db/test_comments.py index 3d43ce2..55c73c3 100644 --- a/tests/db/test_comments.py +++ b/tests/db/test_comments.py @@ -13,134 +13,46 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . import time -from datetime import datetime -from interface.db import get_db -from interface.db.repo import DBRepo -from interface.db.issues import DBIssue -from interface.db.users import DBUser from interface.db.comments import DBComment from interface.db.cache import CACHE_TTL -from interface.utils import since_epoch -from tests.db.test_user import cmp_user -from tests.db.test_issue import cmp_issue - - -def cmp_comment(lhs: DBComment, rhs: DBComment) -> bool: - assert lhs is not None - assert rhs is not None - - return all( - [ - lhs.body == rhs.body, - lhs.created == rhs.created, - lhs.updated == rhs.updated, - lhs.is_native == rhs.is_native, - cmp_user(lhs.user, rhs.user), - cmp_issue(lhs.belongs_to_issue, rhs.belongs_to_issue), - lhs.comment_id == rhs.comment_id, - lhs.html_url == rhs.html_url, - ] - ) +from .utils import cmp_comment, get_comment def test_comment(client): """Test user route""" - # user data signed by interface1 - username = "db_test_user" - user_id = f"{username}@git.batsense.net" - profile_url = f"https://git.batsense.net/{username}" - user = DBUser( - name=username, - user_id=user_id, - profile_url=profile_url, - avatar_url=profile_url, - description="description", - id=None, - ) - user.save() - - # repository data - repo_name = "repo_name" - repo_owner = user.user_id - repo = DBRepo( - name=repo_name, - owner=user, - description="foo", - html_url=f"{profile_url}/{repo_name}", - ) - repo.save() - - title = "Test issue" - description = "foo bar" - repo_scope_id = 8 - html_url = f"https://git.batsense/{repo_owner}/{repo_name}/issues/{repo_scope_id}" - created = since_epoch() - updated = since_epoch() - is_closed = False - is_merged = None - is_native = True - - issue = DBIssue( - title=title, - description=description, - html_url=html_url, - created=created, - updated=updated, - repo_scope_id=repo_scope_id, - repository=repo, - user=user, - is_closed=is_closed, - is_merged=is_merged, - is_native=is_native, - ) - issue.save() - - comment_body = "test comment" + # create comment 1 + repo_scope_id = 99 comment_id1 = 1 - comment_url1 = f"https://git.batsense.net/{repo_owner}/{repo_name}/issues/{repo_scope_id}/{comment_id1}" - comment1 = DBComment( - body=comment_body, - created=since_epoch(), - updated=since_epoch(), - is_native=True, - belongs_to_issue=issue, - user=user, - html_url=comment_url1, - comment_id=comment_id1, - ) - assert DBComment.load_issue_comments(issue) is None + comment1 = get_comment(issue_id=repo_scope_id, comment_id=comment_id1) + assert DBComment.load_issue_comments(comment1.belongs_to_issue) is None assert DBComment.load_from_comment_url(comment1.html_url) is None + + # check comment count, should be 0 as none exists assert DBComment.count.count() == 0 comment1.save() + + # check comment count, should be 0 as one exists but cache hasn't expired yet assert DBComment.count.count() == 0 + + # sleep till cache TTL and check comment count, should b 1 time.sleep(CACHE_TTL * 2) assert DBComment.count.count() == 1 assert comment1.id is not None + # create comment 2 comment_id2 = 2 - comment_url2 = f"https://git.batsense.net/{repo_owner}/{repo_name}/issues/{repo_scope_id}/{comment_id2}" - - comment2 = DBComment( - body=comment_body, - created=since_epoch(), - updated=since_epoch(), - is_native=True, - belongs_to_issue=issue, - user=user, - html_url=comment_url2, - comment_id=comment_id2, - ) - + comment2 = get_comment(issue_id=repo_scope_id + 1, comment_id=comment_id2) comment2.save() - for comment in DBComment.load_issue_comments(issue): - from_url = DBComment.load_from_comment_url(comment.html_url) - assert cmp_comment(comment, from_url) - if comment.comment_id == comment1.comment_id: - assert cmp_comment(comment1, comment) + comments = DBComment.load_issue_comments(comment1.belongs_to_issue) + for dbcomment in comments: + from_url = DBComment.load_from_comment_url(dbcomment.html_url) + assert cmp_comment(dbcomment, from_url) + if dbcomment.comment_id == comment1.comment_id: + assert cmp_comment(comment1, dbcomment) else: - assert cmp_comment(comment2, comment) + assert cmp_comment(comment2, dbcomment) diff --git a/tests/db/test_issue.py b/tests/db/test_issue.py index 9e1a39e..beeec74 100644 --- a/tests/db/test_issue.py +++ b/tests/db/test_issue.py @@ -22,84 +22,17 @@ from interface.utils import since_epoch from interface.db.users import DBUser -from .test_repo import cmp_repo -from .test_user import cmp_user - - -def cmp_issue(lhs: DBIssue, rhs: DBIssue) -> bool: - assert lhs is not None - assert rhs is not None - - return all( - [ - lhs.title == rhs.title, - lhs.description == rhs.description, - lhs.repo_scope_id == rhs.repo_scope_id, - lhs.html_url == rhs.html_url, - lhs.created == rhs.created, - lhs.updated == rhs.updated, - lhs.is_closed == rhs.is_closed, - lhs.is_merged == rhs.is_merged, - lhs.is_native == rhs.is_native, - cmp_repo(lhs.repository, rhs.repository), - cmp_user(lhs.user, rhs.user), - ] - ) + +from .utils import cmp_issue, get_issue, get_pr def test_issue(client): """Test user route""" - # user data signed by interface1 - username = "db_test_user" - user_id = username - profile_url = f"https://git.batsense.net/{username}" - user = DBUser( - name=username, - user_id=user_id, - profile_url=profile_url, - avatar_url=profile_url, - description="description", - id=None, - ) - - user.save() - - # repository data - repo_name = "foo" - repo = DBRepo( - name=repo_name, - description="foo", - owner=user, - html_url=f"{profile_url}/{repo_name}", - ) - - title = "Test issue" - description = "foo bar" - repo_scope_id = 8 - html_url = f"https://git.batsense/{user.user_id}/{repo_name}/issues/{repo_scope_id}" - created = since_epoch() - updated = since_epoch() - # repository= repo - is_closed = False - is_merged = None - is_native = True - - issue = DBIssue( - title=title, - description=description, - html_url=html_url, - created=created, - updated=updated, - repo_scope_id=repo_scope_id, - repository=repo, - user=user, - is_closed=is_closed, - is_merged=is_merged, - is_native=is_native, - ) - assert DBIssue.load(repository=repo, repo_scope_id=repo_scope_id) is None - assert DBIssue.load_with_html_url(html_url=html_url) is None + issue_id = 1 + issue = get_issue(repo_scope_id=issue_id) + assert DBIssue.load(repository=issue.repository, repo_scope_id=issue_id) is None + assert DBIssue.load_with_html_url(html_url=issue.html_url) is None assert DBIssue.load_with_id(db_id=11) is None issue.save() @@ -107,31 +40,16 @@ def test_issue(client): assert issue.id is not None pr_repo_scope_id = 2 - html_url_of_pr = ( - f"https://git.batsense/{user.user_id}/{repo_name}/issues/{pr_repo_scope_id}" - ) - pr = DBIssue( - title="test issue PR", - description=description, - html_url=html_url_of_pr, - created=created, - updated=updated, - repo_scope_id=pr_repo_scope_id, - repository=repo, - user=user, - is_closed=is_closed, - is_merged=False, - is_native=is_native, - ) + pr = get_pr(repo_scope_id=pr_repo_scope_id) pr.save() - pr_from_db = DBIssue.load(repo, repo_scope_id=pr_repo_scope_id) + pr_from_db = DBIssue.load(pr.repository, repo_scope_id=pr.repo_scope_id) assert cmp_issue(pr, pr_from_db) is True - issue_from_db = DBIssue.load(repo, repo_scope_id=repo_scope_id) + issue_from_db = DBIssue.load(issue.repository, repo_scope_id=issue.repo_scope_id) with_id = DBIssue.load_with_id(issue_from_db.id) - with_html_url = DBIssue.load_with_html_url(html_url) + with_html_url = DBIssue.load_with_html_url(issue.html_url) assert cmp_issue(issue_from_db, issue) is True assert cmp_issue(issue_from_db, with_id) is True assert cmp_issue(issue_from_db, with_html_url) is True diff --git a/tests/db/test_repo.py b/tests/db/test_repo.py index 129c018..51449b0 100644 --- a/tests/db/test_repo.py +++ b/tests/db/test_repo.py @@ -16,59 +16,23 @@ from interface.db import DBRepo, DBUser -from .test_user import cmp_user - - -def cmp_repo(lhs: DBRepo, rhs: DBRepo) -> bool: - """Compare two DBRepo objects""" - assert lhs is not None - assert rhs is not None - return all( - [ - lhs.name == rhs.name, - lhs.description == rhs.description, - lhs.html_url == rhs.html_url, - cmp_user(lhs.owner, rhs.owner), - ] - ) +from .utils import cmp_repo, get_repo def test_repo(client): """Test repo""" - # user data signed by interface1 - username = "db_test_user" - user_id = f"{username}@git.batsense.net" - profile_url = f"https://git.batsense.net/{username}" - user = DBUser( - name=username, - user_id=user_id, - profile_url=profile_url, - avatar_url=profile_url, - description="description", - id=None, - ) - - name = "foo" - - repo = DBRepo( - name=name, - owner=user, - description="foo", - id=None, - html_url=f"{profile_url}/{name}", - ) - assert DBRepo.load(name, user.user_id) is None + repo = get_repo() + assert DBRepo.load(repo.name, repo.owner.user_id) is None assert DBRepo.load_with_id(11) is None - user.save() repo.save() - from_db = DBRepo.load(name, user.user_id) + from_db = DBRepo.load(repo.name, repo.owner.user_id) with_id = DBRepo.load_with_id(from_db.id) assert cmp_repo(from_db, repo) assert cmp_repo(from_db, with_id) - from_db2 = DBRepo.load(name, user.user_id) + from_db2 = DBRepo.load(repo.name, repo.owner.user_id) assert cmp_repo(from_db, from_db2) assert from_db.id == from_db2.id diff --git a/tests/db/test_user.py b/tests/db/test_user.py index 1d717e8..3f84382 100644 --- a/tests/db/test_user.py +++ b/tests/db/test_user.py @@ -18,36 +18,15 @@ from interface.db.users import DBUser from interface.db.webfinger import INTERFACE_BASE_URL, INTERFACE_DOMAIN - -def cmp_user(lhs: DBUser, rhs: DBUser) -> bool: - assert lhs is not None - assert rhs is not None - - return all( - [ - lhs.name == rhs.name, - lhs.user_id == rhs.user_id, - lhs.profile_url == rhs.profile_url, - lhs.avatar_url == rhs.avatar_url, - lhs.description == rhs.description, - ] - ) +from .utils import cmp_user, get_user def test_user(client): """Test user route""" - name = "db_test_user" - user_id = name - user = DBUser( - name=name, - user_id=user_id, - profile_url=f"https://git.batsense.net/{user_id}", - avatar_url=f"https://git.batsense.net/{user_id}", - description="description", - ) + user = get_user() - assert DBUser.load(user_id) is None + assert DBUser.load(user.user_id) is None assert DBUser.load_with_db_id(11) is None user.save() diff --git a/tests/db/utils.py b/tests/db/utils.py new file mode 100644 index 0000000..5b93ac5 --- /dev/null +++ b/tests/db/utils.py @@ -0,0 +1,209 @@ +# Bridges software forges to create a distributed software development environment +# Copyright © 2022 Aravinth Manivannan +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from interface.db import get_db, DBComment +from interface.db.repo import DBRepo +from interface.db.issues import DBIssue, OPEN, MERGED, CLOSED +from interface.utils import since_epoch +from interface.db.users import DBUser + + +def cmp_user(lhs: DBUser, rhs: DBUser) -> bool: + assert lhs is not None + assert rhs is not None + + return all( + [ + lhs.name == rhs.name, + lhs.user_id == rhs.user_id, + lhs.profile_url == rhs.profile_url, + lhs.avatar_url == rhs.avatar_url, + lhs.description == rhs.description, + ] + ) + + +def cmp_repo(lhs: DBRepo, rhs: DBRepo) -> bool: + """Compare two DBRepo objects""" + assert lhs is not None + assert rhs is not None + return all( + [ + lhs.name == rhs.name, + lhs.description == rhs.description, + lhs.html_url == rhs.html_url, + cmp_user(lhs.owner, rhs.owner), + ] + ) + + +def cmp_issue(lhs: DBIssue, rhs: DBIssue) -> bool: + assert lhs is not None + assert rhs is not None + + res = [ + lhs.title == rhs.title, + lhs.description == rhs.description, + lhs.repo_scope_id == rhs.repo_scope_id, + lhs.html_url == rhs.html_url, + lhs.created == rhs.created, + lhs.updated == rhs.updated, + lhs.is_closed == rhs.is_closed, + lhs.is_merged == rhs.is_merged, + lhs.is_native == rhs.is_native, + cmp_repo(lhs.repository, rhs.repository), + cmp_user(lhs.user, rhs.user), + ] + + print(f"cmp_issue: {res}") + print(f"{lhs.created} == {rhs.created}") + print(f"{lhs.updated} == {rhs.updated}") + + return all( + [ + lhs.title == rhs.title, + lhs.description == rhs.description, + lhs.repo_scope_id == rhs.repo_scope_id, + lhs.html_url == rhs.html_url, + lhs.created == rhs.created, + lhs.updated == rhs.updated, + lhs.is_closed == rhs.is_closed, + lhs.is_merged == rhs.is_merged, + lhs.is_native == rhs.is_native, + cmp_repo(lhs.repository, rhs.repository), + cmp_user(lhs.user, rhs.user), + ] + ) + + +def cmp_comment(lhs: DBComment, rhs: DBComment) -> bool: + assert lhs is not None + assert rhs is not None + + print(f" lhs: {lhs.id} rhs: {rhs.id}") + + print( + f""" + cmp_comment: + {( + lhs.body == rhs.body, + lhs.created == rhs.created, + lhs.updated == rhs.updated, + lhs.is_native == rhs.is_native, + cmp_user(lhs.user, rhs.user), + cmp_issue(lhs.belongs_to_issue, rhs.belongs_to_issue), + lhs.comment_id == rhs.comment_id, + lhs.html_url == rhs.html_url, + lhs.id == rhs.id + )} + """ + ) + + return all( + [ + lhs.body == rhs.body, + lhs.created == rhs.created, + lhs.updated == rhs.updated, + lhs.is_native == rhs.is_native, + cmp_user(lhs.user, rhs.user), + cmp_issue(lhs.belongs_to_issue, rhs.belongs_to_issue), + lhs.comment_id == rhs.comment_id, + lhs.html_url == rhs.html_url, + lhs.id == rhs.id, + ] + ) + + +USERNAME = "db_test_user" +PROFILE_URL = f"https://git.batsense.net/{USERNAME}" + + +def get_user() -> DBUser: + return DBUser( + name=USERNAME, + user_id=USERNAME, + profile_url=PROFILE_URL, + avatar_url=PROFILE_URL, + description="description", + id=None, + ) + + +REPO_NAME = "foo" + + +def get_repo() -> DBRepo: + owner = get_user() + # owner.save() + return DBRepo( + name=REPO_NAME, + owner=owner, + description="foo", + html_url=f"{PROFILE_URL}/{REPO_NAME}", + ) + + +def get_issue(repo_scope_id: int) -> DBIssue: + title = "Test issue" + description = "foo bar" + repo = get_repo() + # repo.save() + user = get_user() + html_url = f"{repo.html_url}/issues/{repo_scope_id}" + created = since_epoch() + updated = since_epoch() + # repository= repo + is_closed = False + is_merged = None + is_native = True + + return DBIssue( + title=title, + description=description, + html_url=html_url, + created=created, + updated=updated, + repo_scope_id=repo_scope_id, + repository=repo, + user=user, + is_closed=is_closed, + is_merged=is_merged, + is_native=is_native, + ) + + +def get_pr(repo_scope_id: int) -> DBIssue: + pr = get_issue(repo_scope_id) + pr.title = "test issue PR" + pr.is_merged = False + return pr + + +def get_comment(issue_id: int, comment_id: int) -> DBComment: + user = get_user() + issue = get_issue(issue_id) + # issue.save() + comment_body = "test comment" + comment_url1 = f"{issue.html_url}/{comment_id}" + return DBComment( + body=comment_body, + created=since_epoch(), + updated=since_epoch(), + is_native=True, + belongs_to_issue=issue, + user=user, + html_url=comment_url1, + comment_id=comment_id, + ) From 3e42383c50b18f4ba0030b61805242b1bf13c393 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Fri, 15 Apr 2022 10:36:44 +0530 Subject: [PATCH 5/5] feat: cache DB queries --- interface/git.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/interface/git.py b/interface/git.py index 220fe1f..bb421e0 100644 --- a/interface/git.py +++ b/interface/git.py @@ -18,6 +18,8 @@ # along with this program. If not, see . import datetime from urllib.parse import urlparse +from functools import lru_cache + import rfc3339 from flask import g @@ -30,6 +32,8 @@ from interface.forges.gitea import Gitea from interface.forges.payload import RepositoryInfo +REPOSITORY_READ_LIMIT = 50 + class Git: def __init__(self, forge: Forge, admin_user: str, admin_email): @@ -114,6 +118,7 @@ def get_forge() -> Git: return g.git +@lru_cache(maxsize=20) def get_user(username: str) -> DBUser: """ Get user from database. @@ -128,6 +133,7 @@ def get_user(username: str) -> DBUser: return user +@lru_cache(maxsize=20) def __get_and_store_repo(owner: str, name: str) -> DBRepo: git = get_forge() print(f" requesting data for user {owner}") @@ -167,6 +173,7 @@ def get_repo(owner: str, name: str) -> DBRepo: return repo +@lru_cache(maxsize=20) def __get_and_store_issue(owner: str, repo: str, issue_id: int) -> DBRepo: git = get_forge() issue_url = git.forge.get_issue_html_url(owner=owner, repo=repo, issue_id=issue_id)