mirror of
https://github.com/yzernik/squeaknode.git
synced 2026-08-18 13:09:08 +02:00
Use timestamp for like field (#896)
* Use a timestamp for like field in database * Use query to get liked squeaks in order of like
This commit is contained in:
parent
a5b5d417d5
commit
b935785469
10 changed files with 111 additions and 35 deletions
|
|
@ -1363,6 +1363,18 @@ def test_get_squeak_details(server_stub, admin_stub, saved_squeak_hash):
|
|||
|
||||
|
||||
def test_like_squeak(server_stub, admin_stub, saved_squeak_hash):
|
||||
# Get the squeak display item
|
||||
get_squeak_display_response = admin_stub.GetSqueakDisplay(
|
||||
squeak_admin_pb2.GetSqueakDisplayRequest(
|
||||
squeak_hash=saved_squeak_hash,
|
||||
)
|
||||
)
|
||||
print("get_squeak_display_response.squeak_display_entry:")
|
||||
print(get_squeak_display_response.squeak_display_entry)
|
||||
assert (
|
||||
get_squeak_display_response.squeak_display_entry.liked_time_s == 0
|
||||
)
|
||||
|
||||
# Like the squeak
|
||||
admin_stub.LikeSqueak(
|
||||
squeak_admin_pb2.LikeSqueakRequest(
|
||||
|
|
@ -1377,7 +1389,7 @@ def test_like_squeak(server_stub, admin_stub, saved_squeak_hash):
|
|||
)
|
||||
)
|
||||
assert (
|
||||
get_squeak_display_response.squeak_display_entry.liked
|
||||
get_squeak_display_response.squeak_display_entry.liked_time_s > 0
|
||||
)
|
||||
|
||||
# Unlike the squeak
|
||||
|
|
@ -1394,5 +1406,5 @@ def test_like_squeak(server_stub, admin_stub, saved_squeak_hash):
|
|||
)
|
||||
)
|
||||
assert (
|
||||
not get_squeak_display_response.squeak_display_entry.liked
|
||||
get_squeak_display_response.squeak_display_entry.liked_time_s == 0
|
||||
)
|
||||
|
|
|
|||
|
|
@ -488,8 +488,8 @@ message SqueakDisplayEntry {
|
|||
/// The author name
|
||||
SqueakProfile author = 11;
|
||||
|
||||
/// Is liked
|
||||
bool liked = 12;
|
||||
/// Liked time
|
||||
int64 liked_time_s = 12;
|
||||
}
|
||||
|
||||
message GetTimelineSqueakDisplaysRequest {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ def squeak_entry_to_message(squeak_entry_with_profile: SqueakEntryWithProfile) -
|
|||
squeak_entry = squeak_entry_with_profile.squeak_entry
|
||||
squeak = squeak_entry.squeak
|
||||
block_header = squeak_entry.block_header
|
||||
liked = squeak_entry.liked
|
||||
liked_time_s = squeak_entry.liked_time or 0
|
||||
is_unlocked = squeak.HasDecryptionKey()
|
||||
content_str = squeak.GetDecryptedContentStr() if is_unlocked else None
|
||||
is_reply = squeak.is_reply
|
||||
|
|
@ -49,7 +49,7 @@ def squeak_entry_to_message(squeak_entry_with_profile: SqueakEntryWithProfile) -
|
|||
author_address=author_address,
|
||||
is_author_known=is_author_known,
|
||||
author=profile_msg,
|
||||
liked=liked,
|
||||
liked_time_s=liked_time_s,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ class SqueakAdminServerHandler(object):
|
|||
)
|
||||
)
|
||||
logger.info("Returning squeak display entry with like value: {}".format(
|
||||
squeak_entry_with_profile.squeak_entry.liked,
|
||||
squeak_entry_with_profile.squeak_entry.liked_time,
|
||||
))
|
||||
display_message = squeak_entry_to_message(
|
||||
squeak_entry_with_profile)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from typing import NamedTuple
|
||||
from typing import Optional
|
||||
|
||||
from bitcoin.core import CBlockHeader
|
||||
from squeak.core import CSqueak
|
||||
|
|
@ -7,4 +8,4 @@ from squeak.core import CSqueak
|
|||
class SqueakEntry(NamedTuple):
|
||||
squeak: CSqueak
|
||||
block_header: CBlockHeader
|
||||
liked: bool = False
|
||||
liked_time: Optional[int] = None
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
"""Use timestamp for liked field
|
||||
|
||||
Revision ID: c874732c09b6
|
||||
Revises: f62215acb987
|
||||
Create Date: 2021-06-04 17:03:56.626831
|
||||
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
import squeaknode.db.models
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c874732c09b6'
|
||||
down_revision = 'f62215acb987'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('squeak', schema=None) as batch_op:
|
||||
batch_op.add_column(
|
||||
sa.Column('liked_time', squeaknode.db.models.TZDateTime(), nullable=True))
|
||||
batch_op.drop_column('liked')
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
with op.batch_alter_table('squeak', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('liked', sa.BOOLEAN(),
|
||||
server_default=sa.text('0'), nullable=False))
|
||||
batch_op.drop_column('liked_time')
|
||||
|
||||
# ### end Alembic commands ###
|
||||
|
|
@ -70,7 +70,8 @@ class Models:
|
|||
Column("author_address", String(35), index=True, nullable=False),
|
||||
Column("secret_key", String(64), nullable=True),
|
||||
Column("block_header", Binary, nullable=False),
|
||||
Column("liked", Boolean, nullable=False, default=False),
|
||||
Column("liked_time", TZDateTime,
|
||||
default=None, nullable=True),
|
||||
)
|
||||
|
||||
self.profiles = Table(
|
||||
|
|
|
|||
|
|
@ -90,11 +90,11 @@ class SqueakDb:
|
|||
|
||||
@property
|
||||
def squeak_is_liked(self):
|
||||
return self.squeaks.c.liked
|
||||
return self.squeaks.c.liked_time != None # noqa: E711
|
||||
|
||||
@property
|
||||
def squeak_is_not_liked(self):
|
||||
return self.squeaks.c.liked == False # noqa: E711
|
||||
return self.squeaks.c.liked_time == None # noqa: E711
|
||||
|
||||
@property
|
||||
def squeak_has_no_secret_key(self):
|
||||
|
|
@ -218,10 +218,7 @@ class SqueakDb:
|
|||
return None
|
||||
return self._parse_squeak_entry_with_profile(row)
|
||||
|
||||
def get_timeline_squeak_entries_with_profile(
|
||||
self,
|
||||
only_liked: bool = False,
|
||||
) -> List[SqueakEntryWithProfile]:
|
||||
def get_timeline_squeak_entries_with_profile(self) -> List[SqueakEntryWithProfile]:
|
||||
""" Get all followed squeaks. """
|
||||
s = (
|
||||
select([self.squeaks, self.profiles])
|
||||
|
|
@ -231,12 +228,6 @@ class SqueakDb:
|
|||
self.profiles.c.address == self.squeaks.c.author_address,
|
||||
)
|
||||
)
|
||||
.where(
|
||||
or_(
|
||||
self.squeak_is_liked,
|
||||
not only_liked,
|
||||
)
|
||||
)
|
||||
.order_by(
|
||||
self.squeaks.c.n_block_height.desc(),
|
||||
self.squeaks.c.n_time.desc(),
|
||||
|
|
@ -247,6 +238,28 @@ class SqueakDb:
|
|||
rows = result.fetchall()
|
||||
return [self._parse_squeak_entry_with_profile(row) for row in rows]
|
||||
|
||||
def get_liked_squeak_entries_with_profile(self) -> List[SqueakEntryWithProfile]:
|
||||
""" Get liked squeaks. """
|
||||
s = (
|
||||
select([self.squeaks, self.profiles])
|
||||
.select_from(
|
||||
self.squeaks.outerjoin(
|
||||
self.profiles,
|
||||
self.profiles.c.address == self.squeaks.c.author_address,
|
||||
)
|
||||
)
|
||||
.where(
|
||||
self.squeak_is_liked,
|
||||
)
|
||||
.order_by(
|
||||
self.squeaks.c.liked_time.desc(),
|
||||
)
|
||||
)
|
||||
with self.get_connection() as connection:
|
||||
result = connection.execute(s)
|
||||
rows = result.fetchall()
|
||||
return [self._parse_squeak_entry_with_profile(row) for row in rows]
|
||||
|
||||
def get_squeak_entries_with_profile_for_address(
|
||||
self, address: str, min_block: int, max_block: int
|
||||
) -> List[SqueakEntryWithProfile]:
|
||||
|
|
@ -622,12 +635,22 @@ class SqueakDb:
|
|||
with self.get_connection() as connection:
|
||||
connection.execute(stmt)
|
||||
|
||||
def set_squeak_liked(self, squeak_hash: bytes, liked: bool) -> None:
|
||||
""" Set the liked value of a squeak. """
|
||||
def set_squeak_liked(self, squeak_hash: bytes) -> None:
|
||||
""" Set the squeak to be liked. """
|
||||
stmt = (
|
||||
self.squeaks.update()
|
||||
.where(self.squeaks.c.hash == squeak_hash.hex())
|
||||
.values(liked=liked)
|
||||
.values(liked_time=self.datetime_now)
|
||||
)
|
||||
with self.get_connection() as connection:
|
||||
connection.execute(stmt)
|
||||
|
||||
def set_squeak_unliked(self, squeak_hash: bytes) -> None:
|
||||
""" Set the squeak to be unliked. """
|
||||
stmt = (
|
||||
self.squeaks.update()
|
||||
.where(self.squeaks.c.hash == squeak_hash.hex())
|
||||
.values(liked_time=None)
|
||||
)
|
||||
with self.get_connection() as connection:
|
||||
connection.execute(stmt)
|
||||
|
|
@ -1121,11 +1144,12 @@ class SqueakDb:
|
|||
parse_block_header(block_header_bytes) if
|
||||
block_header_bytes else None
|
||||
)
|
||||
liked = row["liked"]
|
||||
liked_time = row["liked_time"]
|
||||
liked_time_s = int(liked_time.timestamp()) if liked_time else None
|
||||
return SqueakEntry(
|
||||
squeak=squeak,
|
||||
block_header=block_header,
|
||||
liked=liked,
|
||||
liked_time=liked_time_s,
|
||||
)
|
||||
|
||||
def _parse_squeak_profile(self, row) -> SqueakProfile:
|
||||
|
|
|
|||
|
|
@ -450,9 +450,7 @@ class SqueakController:
|
|||
return self.squeak_db.get_timeline_squeak_entries_with_profile()
|
||||
|
||||
def get_liked_squeak_entries_with_profile(self):
|
||||
return self.squeak_db.get_timeline_squeak_entries_with_profile(
|
||||
only_liked=True,
|
||||
)
|
||||
return self.squeak_db.get_liked_squeak_entries_with_profile()
|
||||
|
||||
def get_squeak_entries_with_profile_for_address(
|
||||
self, address: str, min_block: int, max_block: int
|
||||
|
|
@ -503,9 +501,13 @@ class SqueakController:
|
|||
self.payment_processor.start_processing()
|
||||
|
||||
def delete_old_squeaks(self):
|
||||
logger.info("Deleting old squeaks...")
|
||||
squeaks_to_delete = self.squeak_db.get_old_squeaks_to_delete(
|
||||
self.config.core.squeak_retention_s,
|
||||
)
|
||||
logger.info("Got old squeakd to delete: {}".format(
|
||||
squeaks_to_delete,
|
||||
))
|
||||
for squeak_entry_with_profile in squeaks_to_delete:
|
||||
squeak = squeak_entry_with_profile.squeak_entry.squeak
|
||||
squeak_hash = get_hash(squeak)
|
||||
|
|
@ -522,14 +524,12 @@ class SqueakController:
|
|||
))
|
||||
self.squeak_db.set_squeak_liked(
|
||||
squeak_hash,
|
||||
True,
|
||||
)
|
||||
|
||||
def unlike_squeak(self, squeak_hash: bytes):
|
||||
logger.info("Unliking squeak: {}".format(
|
||||
squeak_hash.hex(),
|
||||
))
|
||||
self.squeak_db.set_squeak_liked(
|
||||
self.squeak_db.set_squeak_unliked(
|
||||
squeak_hash,
|
||||
False,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ class TimelineDownloadSync(DownloadSync):
|
|||
try:
|
||||
peer_connection.download(self.block_interval)
|
||||
except Exception:
|
||||
logger.info("Failed to download timeline from peer: {}".format(
|
||||
logger.exception("Failed to download timeline from peer: {}".format(
|
||||
peer_connection.peer_address,
|
||||
))
|
||||
|
||||
|
|
@ -106,11 +106,10 @@ class SingleSqueakDownloadSync(DownloadSync):
|
|||
try:
|
||||
peer_connection.download_single_squeak(self.squeak_hash)
|
||||
except Exception:
|
||||
logger.info("Failed to download single squeak: {} from peer: {}".format(
|
||||
logger.exception("Failed to download single squeak: {} from peer: {}".format(
|
||||
self.squeak_hash.hex(),
|
||||
peer_connection.peer_address,
|
||||
))
|
||||
logger.error("Download single squeak error:", exc_info=True)
|
||||
|
||||
|
||||
class TimelineUploadSync(UploadSync):
|
||||
|
|
@ -132,6 +131,7 @@ class TimelineUploadSync(UploadSync):
|
|||
logger.info("Failed to upload timeline to peer: {}".format(
|
||||
peer_connection.peer_address,
|
||||
))
|
||||
logger.exception("Failed to upload timeline to peer")
|
||||
|
||||
|
||||
class SingleSqueakUploadSync(UploadSync):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue