Change create time sent payment to integer (#1221)

* Change created time in sent payment to milliseconds integer

* Change time field of sent payment rpc message to ms

* Update frontend for sent payment to get new milliseconds field

* Update frontend build

* Use milliseconds for received offer created time in database

* Use milliseconds for sent offer created time in database

* Change created time to milliseconds for received payment

* Update frontend to use milliseconds for received payment

* Update frontend to use milliseconds for peer and profile in database

* Change created time and liked time to milliseconds for squeak

* Remove use of datetime module from squeak db

* Fix get liked time in milliseconds in frontend

* Update frontend build

* Simplify squeak retention query
This commit is contained in:
Jonathan Zernik 2021-09-07 21:14:17 -07:00 committed by GitHub
parent 4b76ad832d
commit dc524f80ec
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 460 additions and 97 deletions

View file

@ -84,7 +84,7 @@ export default function ReceivedPayment({
alignItems="flex-start"
>
<Grid item>
{moment(receivedPayment.getTimeS() * 1000).format('DD MMM YYYY hh:mm a')}
{moment(receivedPayment.getTimeMs()).format('DD MMM YYYY hh:mm a')}
</Grid>
</Grid>
<Grid

View file

@ -91,7 +91,7 @@ export default function SentPayment({
alignItems="flex-start"
>
<Grid item>
{moment(sentPayment.getTimeS() * 1000).format('DD MMM YYYY hh:mm a')}
{moment(sentPayment.getTimeMs()).format('DD MMM YYYY hh:mm a')}
</Grid>
</Grid>
<Grid

View file

@ -224,7 +224,7 @@ export default function SqueakActionBar({
}
function LikeIconContent() {
if (squeak && !squeak.getLikedTimeS()) {
if (squeak && !squeak.getLikedTimeMs()) {
return (
<IconButton
aria-label="like"

View file

@ -676,11 +676,11 @@ def test_buy_squeak(
]
assert sent_payment.payment_hash in payment_hashes
for received_payment in get_received_payments_response.received_payments:
received_payment_time_s = received_payment.time_s
received_payment_time_ms = received_payment.time_ms
# print("received_payment_time_s: {}".format(
# received_payment_time_s))
received_payment_time = datetime.datetime.fromtimestamp(
received_payment_time_s
received_payment_time_ms / 1000,
)
five_minutes = datetime.timedelta(minutes=5)
assert received_payment_time > datetime.datetime.now() - five_minutes
@ -869,7 +869,7 @@ def test_like_squeak(admin_stub, saved_squeak_hash):
get_squeak_display_entry = get_squeak_display(
admin_stub, saved_squeak_hash)
assert (
get_squeak_display_entry.liked_time_s == 0
get_squeak_display_entry.liked_time_ms == 0
)
# Like the squeak
@ -883,7 +883,7 @@ def test_like_squeak(admin_stub, saved_squeak_hash):
get_squeak_display_entry = get_squeak_display(
admin_stub, saved_squeak_hash)
assert (
get_squeak_display_entry.liked_time_s > 0
get_squeak_display_entry.liked_time_ms > 0
)
# Unlike the squeak
@ -897,7 +897,7 @@ def test_like_squeak(admin_stub, saved_squeak_hash):
get_squeak_display_entry = get_squeak_display(
admin_stub, saved_squeak_hash)
assert (
get_squeak_display_entry.liked_time_s == 0
get_squeak_display_entry.liked_time_ms == 0
)

View file

@ -582,7 +582,7 @@ message SqueakDisplayEntry {
SqueakProfile author = 12;
/// Liked time
int64 liked_time_s = 13;
int64 liked_time_ms = 13;
}
message GetTimelineSqueakDisplaysRequest {
@ -851,7 +851,7 @@ message SentPayment {
bool valid = 6;
/// Time of payment
int64 time_s = 7;
int64 time_ms = 7;
/// The address of the squeak peer
PeerAddress peer_address = 8;
@ -948,7 +948,7 @@ message ReceivedPayment {
int64 price_msat = 4;
/// Time of payment
int64 time_s = 5;
int64 time_ms = 5;
/// The address of the squeak peer
PeerAddress peer_address = 6;

View file

@ -20,8 +20,6 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import logging
from datetime import datetime
from datetime import timezone
from squeak.core import CSqueak
@ -68,7 +66,7 @@ def squeak_entry_to_message(squeak_entry: SqueakEntry) -> squeak_admin_pb2.Squea
author_address=squeak_entry.address,
is_author_known=is_author_known,
author=profile_msg,
liked_time_s=squeak_entry.liked_time, # type: ignore
liked_time_ms=squeak_entry.liked_time_ms, # type: ignore
)
@ -122,8 +120,8 @@ def offer_entry_to_message(received_offer: ReceivedOffer) -> squeak_admin_pb2.Of
def sent_payment_to_message(sent_payment: SentPayment) -> squeak_admin_pb2.SentPayment:
if sent_payment.sent_payment_id is None:
raise Exception("Sent payment id cannot be None.")
if sent_payment.created is None:
raise Exception("Sent payment created time not found.")
if sent_payment.created_time_ms is None:
raise Exception("Sent payment created time ms not found.")
return squeak_admin_pb2.SentPayment(
sent_payment_id=sent_payment.sent_payment_id,
squeak_hash=sent_payment.squeak_hash.hex(),
@ -131,7 +129,7 @@ def sent_payment_to_message(sent_payment: SentPayment) -> squeak_admin_pb2.SentP
price_msat=sent_payment.price_msat,
node_pubkey=sent_payment.node_pubkey,
valid=sent_payment.valid,
time_s=int(sent_payment.created.timestamp()),
time_ms=sent_payment.created_time_ms,
peer_address=peer_address_to_message(sent_payment.peer_address)
)
@ -157,14 +155,14 @@ def sent_offer_to_message(sent_offer: SentOffer) -> squeak_admin_pb2.SentOffer:
def received_payments_to_message(received_payment: ReceivedPayment) -> squeak_admin_pb2.ReceivedPayment:
if received_payment.received_payment_id is None:
raise Exception("Received payment id cannot be None.")
if received_payment.created is None:
raise Exception("Received payment created time not found.")
if received_payment.created_time_ms is None:
raise Exception("Received payment created time ms not found.")
return squeak_admin_pb2.ReceivedPayment(
received_payment_id=received_payment.received_payment_id,
squeak_hash=received_payment.squeak_hash.hex(),
payment_hash=received_payment.payment_hash.hex(),
price_msat=received_payment.price_msat,
time_s=int(received_payment.created.timestamp()),
time_ms=received_payment.created_time_ms,
peer_address=peer_address_to_message(received_payment.peer_address)
)
@ -219,7 +217,7 @@ def message_to_squeak_entry(squeak_entry: squeak_admin_pb2.SqueakDisplayEntry) -
squeak_entry.reply_to) if squeak_entry.reply_to else None,
is_unlocked=squeak_entry.is_unlocked,
squeak_profile=None, # TODO: message to squeak profile
liked_time=squeak_entry.liked_time_s,
liked_time_ms=squeak_entry.liked_time_ms,
content=squeak_entry.content_str,
)
@ -227,7 +225,7 @@ def message_to_squeak_entry(squeak_entry: squeak_admin_pb2.SqueakDisplayEntry) -
def message_to_sent_payment(sent_payment: squeak_admin_pb2.SentPayment) -> SentPayment:
return SentPayment(
sent_payment_id=sent_payment.sent_payment_id,
created=timestamp_to_datetime(sent_payment.time_s),
created_time_ms=sent_payment.time_ms,
peer_address=message_to_peer_address(sent_payment.peer_address),
squeak_hash=bytes.fromhex(sent_payment.squeak_hash),
payment_hash=bytes.fromhex(sent_payment.payment_hash),
@ -236,7 +234,3 @@ def message_to_sent_payment(sent_payment: squeak_admin_pb2.SentPayment) -> SentP
node_pubkey=sent_payment.node_pubkey,
valid=sent_payment.valid,
)
def timestamp_to_datetime(timestamp: int) -> datetime:
return datetime.fromtimestamp(timestamp, timezone.utc)

View file

@ -1,14 +1,14 @@
{
"files": {
"main.js": "/static/js/main.c017f06a.chunk.js",
"main.js.map": "/static/js/main.c017f06a.chunk.js.map",
"main.js": "/static/js/main.b185b1a7.chunk.js",
"main.js.map": "/static/js/main.b185b1a7.chunk.js.map",
"runtime-main.js": "/static/js/runtime-main.9f0ba400.js",
"runtime-main.js.map": "/static/js/runtime-main.9f0ba400.js.map",
"static/css/2.ea4ba2f0.chunk.css": "/static/css/2.ea4ba2f0.chunk.css",
"static/js/2.73e108c6.chunk.js": "/static/js/2.73e108c6.chunk.js",
"static/js/2.73e108c6.chunk.js.map": "/static/js/2.73e108c6.chunk.js.map",
"index.html": "/index.html",
"precache-manifest.98527034402653794ed933617b9ff8d5.js": "/precache-manifest.98527034402653794ed933617b9ff8d5.js",
"precache-manifest.f5f2492faa6e868a5f1b2d46bb8144db.js": "/precache-manifest.f5f2492faa6e868a5f1b2d46bb8144db.js",
"service-worker.js": "/service-worker.js",
"static/css/2.ea4ba2f0.chunk.css.map": "/static/css/2.ea4ba2f0.chunk.css.map",
"static/js/2.73e108c6.chunk.js.LICENSE.txt": "/static/js/2.73e108c6.chunk.js.LICENSE.txt",
@ -20,6 +20,6 @@
"static/js/runtime-main.9f0ba400.js",
"static/css/2.ea4ba2f0.chunk.css",
"static/js/2.73e108c6.chunk.js",
"static/js/main.c017f06a.chunk.js"
"static/js/main.b185b1a7.chunk.js"
]
}

View file

@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.73e108c6.chunk.js"></script><script src="/static/js/main.c017f06a.chunk.js"></script></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.ea4ba2f0.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.73e108c6.chunk.js"></script><script src="/static/js/main.b185b1a7.chunk.js"></script></body></html>

View file

@ -1,6 +1,6 @@
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "bc8b0db3dd20a409a07d5a51f9d8271f",
"revision": "864a5aa83a22b34be5ea2461efb38eb2",
"url": "/index.html"
},
{
@ -16,8 +16,8 @@ self.__precacheManifest = (self.__precacheManifest || []).concat([
"url": "/static/js/2.73e108c6.chunk.js.LICENSE.txt"
},
{
"revision": "e9f6eb5e38da474d1d0a",
"url": "/static/js/main.c017f06a.chunk.js"
"revision": "c92d37fe13753e88ca70",
"url": "/static/js/main.b185b1a7.chunk.js"
},
{
"revision": "cc9816de5a8639d377ea",

View file

@ -14,7 +14,7 @@
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
importScripts(
"/precache-manifest.98527034402653794ed933617b9ff8d5.js"
"/precache-manifest.f5f2492faa6e868a5f1b2d46bb8144db.js"
);
self.addEventListener('message', (event) => {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -19,7 +19,6 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from datetime import datetime
from typing import NamedTuple
from typing import Optional
@ -29,7 +28,7 @@ from squeaknode.core.peer_address import PeerAddress
class ReceivedPayment(NamedTuple):
"""Represents an payment received by a seller."""
received_payment_id: Optional[int]
created: Optional[datetime]
created_time_ms: Optional[int]
squeak_hash: bytes
payment_hash: bytes
price_msat: int

View file

@ -19,7 +19,6 @@
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
from datetime import datetime
from typing import NamedTuple
from typing import Optional
@ -29,7 +28,7 @@ from squeaknode.core.peer_address import PeerAddress
class SentPayment(NamedTuple):
"""Represents a payment made by a buyer."""
sent_payment_id: Optional[int]
created: Optional[datetime]
created_time_ms: Optional[int]
peer_address: PeerAddress
squeak_hash: bytes
payment_hash: bytes

View file

@ -289,7 +289,7 @@ class SqueakCore:
)
return SentPayment(
sent_payment_id=None,
created=None,
created_time_ms=None,
peer_address=peer_address,
squeak_hash=received_offer.squeak_hash,
payment_hash=received_offer.payment_hash,
@ -333,7 +333,7 @@ class SqueakCore:
sent_offer = get_sent_offer_fn(payment_hash)
yield ReceivedPayment(
received_payment_id=None,
created=None,
created_time_ms=None,
squeak_hash=sent_offer.squeak_hash,
payment_hash=sent_offer.payment_hash,
price_msat=sent_offer.price_msat,

View file

@ -35,5 +35,5 @@ class SqueakEntry(NamedTuple):
reply_to: Optional[bytes]
is_unlocked: bool
squeak_profile: Optional[SqueakProfile]
liked_time: Optional[int] = None
liked_time_ms: Optional[int] = None
content: Optional[str] = None

View file

@ -0,0 +1,60 @@
# MIT License
#
# Copyright (c) 2020 Jonathan Zernik
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Change created time of received offer to integer of milliseconds
Revision ID: 343abc9ed37f
Revises: cc2c5805b8e7
Create Date: 2021-09-07 17:22:38.787649
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy import text
import squeaknode.db.models
# revision identifiers, used by Alembic.
revision = '343abc9ed37f'
down_revision = 'cc2c5805b8e7'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('received_offer', schema=None) as batch_op:
batch_op.add_column(sa.Column('created_time_ms', squeaknode.db.models.SLBigInteger(
), server_default=text('0'), nullable=False))
batch_op.drop_column('created')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('received_offer', schema=None) as batch_op:
batch_op.add_column(sa.Column('created', sa.DATETIME(
), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False))
batch_op.drop_column('created_time_ms')
# ### end Alembic commands ###

View file

@ -0,0 +1,66 @@
# MIT License
#
# Copyright (c) 2020 Jonathan Zernik
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Change created time and liked time of squeak to milliseconds
Revision ID: 67f0f9fda119
Revises: ce9711add3a8
Create Date: 2021-09-07 19:10:21.141214
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy import text
import squeaknode.db.models
# revision identifiers, used by Alembic.
revision = '67f0f9fda119'
down_revision = 'ce9711add3a8'
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('created_time_ms', squeaknode.db.models.SLBigInteger(
), server_default=text('0'), nullable=False))
batch_op.add_column(
sa.Column('liked_time_ms', squeaknode.db.models.SLBigInteger(), nullable=True))
batch_op.drop_column('created')
batch_op.drop_column('liked_time')
# ### 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_time', sa.DATETIME(), nullable=True))
batch_op.add_column(sa.Column('created', sa.DATETIME(
), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False))
batch_op.drop_column('liked_time_ms')
batch_op.drop_column('created_time_ms')
# ### end Alembic commands ###

View file

@ -0,0 +1,60 @@
# MIT License
#
# Copyright (c) 2020 Jonathan Zernik
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Change created time of received payment to integer of milliseconds
Revision ID: 6fffc8dcaae7
Revises: e2fcbdcc0f44
Create Date: 2021-09-07 18:06:26.069174
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy import text
import squeaknode.db.models
# revision identifiers, used by Alembic.
revision = '6fffc8dcaae7'
down_revision = 'e2fcbdcc0f44'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('received_payment', schema=None) as batch_op:
batch_op.add_column(sa.Column('created_time_ms', squeaknode.db.models.SLBigInteger(
), server_default=text('0'), nullable=False))
batch_op.drop_column('created')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('received_payment', schema=None) as batch_op:
batch_op.add_column(sa.Column('created', sa.DATETIME(
), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False))
batch_op.drop_column('created_time_ms')
# ### end Alembic commands ###

View file

@ -0,0 +1,60 @@
# MIT License
#
# Copyright (c) 2020 Jonathan Zernik
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Change created time of sent payment to integer of milliseconds
Revision ID: cc2c5805b8e7
Revises: af0082f29c93
Create Date: 2021-09-07 16:09:57.879198
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy import text
import squeaknode.db.models
# revision identifiers, used by Alembic.
revision = 'cc2c5805b8e7'
down_revision = 'af0082f29c93'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('sent_payment', schema=None) as batch_op:
batch_op.add_column(sa.Column(
'created_time_ms', squeaknode.db.models.SLBigInteger(), server_default=text('0'), nullable=False))
batch_op.drop_column('created')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('sent_payment', schema=None) as batch_op:
batch_op.add_column(sa.Column('created', sa.DATETIME(
), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False))
batch_op.drop_column('created_time_ms')
# ### end Alembic commands ###

View file

@ -0,0 +1,70 @@
# MIT License
#
# Copyright (c) 2020 Jonathan Zernik
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Change created time of peer and profile to integer of milliseconds
Revision ID: ce9711add3a8
Revises: 6fffc8dcaae7
Create Date: 2021-09-07 18:56:07.280945
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy import text
import squeaknode.db.models
# revision identifiers, used by Alembic.
revision = 'ce9711add3a8'
down_revision = '6fffc8dcaae7'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('peer', schema=None) as batch_op:
batch_op.add_column(sa.Column('created_time_ms', squeaknode.db.models.SLBigInteger(
), server_default=text('0'), nullable=False))
batch_op.drop_column('created')
with op.batch_alter_table('profile', schema=None) as batch_op:
batch_op.add_column(sa.Column('created_time_ms', squeaknode.db.models.SLBigInteger(
), server_default=text('0'), nullable=False))
batch_op.drop_column('created')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('profile', schema=None) as batch_op:
batch_op.add_column(sa.Column('created', sa.DATETIME(
), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False))
batch_op.drop_column('created_time_ms')
with op.batch_alter_table('peer', schema=None) as batch_op:
batch_op.add_column(sa.Column('created', sa.DATETIME(
), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False))
batch_op.drop_column('created_time_ms')
# ### end Alembic commands ###

View file

@ -0,0 +1,60 @@
# MIT License
#
# Copyright (c) 2020 Jonathan Zernik
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Change created time of sent offer to integer of milliseconds
Revision ID: e2fcbdcc0f44
Revises: 343abc9ed37f
Create Date: 2021-09-07 17:48:51.672630
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy import text
import squeaknode.db.models
# revision identifiers, used by Alembic.
revision = 'e2fcbdcc0f44'
down_revision = '343abc9ed37f'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('sent_offer', schema=None) as batch_op:
batch_op.add_column(sa.Column('created_time_ms', squeaknode.db.models.SLBigInteger(
), server_default=text('0'), nullable=False))
batch_op.drop_column('created')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('sent_offer', schema=None) as batch_op:
batch_op.add_column(sa.Column('created', sa.DATETIME(
), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False))
batch_op.drop_column('created_time_ms')
# ### end Alembic commands ###

View file

@ -27,7 +27,6 @@ from sqlalchemy import Binary
from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import DateTime
from sqlalchemy import func
from sqlalchemy import Integer
from sqlalchemy import MetaData
from sqlalchemy import String
@ -58,6 +57,9 @@ class TZDateTime(TypeDecorator):
return value
logger = logging.getLogger(__name__)
class SLBigInteger(BigInteger):
pass
@ -81,8 +83,7 @@ class Models:
"squeak",
self.metadata,
Column("hash", Binary(32), primary_key=True),
Column("created", TZDateTime,
server_default=func.now(), nullable=False),
Column("created_time_ms", SLBigInteger, nullable=False),
Column("squeak", Binary, nullable=False),
Column("hash_reply_sqk", Binary(32), nullable=True),
Column("hash_block", Binary(32), nullable=False),
@ -91,8 +92,7 @@ class Models:
Column("author_address", String(35), index=True, nullable=False),
Column("secret_key", Binary(32), nullable=True),
Column("block_time", Integer, nullable=False),
Column("liked_time", TZDateTime,
default=None, nullable=True),
Column("liked_time_ms", SLBigInteger, default=None, nullable=True),
Column("content", String(280), nullable=True),
)
@ -100,8 +100,7 @@ class Models:
"profile",
self.metadata,
Column("profile_id", Integer, primary_key=True),
Column("created", TZDateTime,
server_default=func.now(), nullable=False),
Column("created_time_ms", SLBigInteger, nullable=False),
Column("profile_name", String, unique=True, nullable=False),
Column("private_key", Binary, nullable=True),
Column("address", String(35), unique=True, nullable=False),
@ -116,8 +115,7 @@ class Models:
"peer",
self.metadata,
Column("peer_id", Integer, primary_key=True),
Column("created", TZDateTime,
server_default=func.now(), nullable=False),
Column("created_time_ms", SLBigInteger, nullable=False),
Column("peer_name", String, nullable=False),
Column("host", String, nullable=False),
Column("port", Integer, nullable=False),
@ -131,8 +129,7 @@ class Models:
"received_offer",
self.metadata,
Column("received_offer_id", SLBigInteger, primary_key=True),
Column("created", TZDateTime,
server_default=func.now(), nullable=False),
Column("created_time_ms", SLBigInteger, nullable=False),
Column("squeak_hash", Binary(32), nullable=False),
Column("payment_hash", Binary(32), unique=True, nullable=False),
Column("nonce", Binary(32), nullable=False),
@ -154,8 +151,7 @@ class Models:
"sent_payment",
self.metadata,
Column("sent_payment_id", SLBigInteger, primary_key=True),
Column("created", TZDateTime,
server_default=func.now(), nullable=False),
Column("created_time_ms", SLBigInteger, nullable=False),
Column("peer_host", String, nullable=False),
Column("peer_port", Integer, nullable=False),
Column("squeak_hash", Binary(32), nullable=False),
@ -171,8 +167,7 @@ class Models:
"sent_offer",
self.metadata,
Column("sent_offer_id", SLBigInteger, primary_key=True),
Column("created", TZDateTime,
server_default=func.now(), nullable=False),
Column("created_time_ms", SLBigInteger, nullable=False),
Column("squeak_hash", Binary(32), nullable=False),
Column("payment_hash", Binary(32), unique=True, nullable=False),
Column("secret_key", Binary(32), nullable=False),
@ -191,8 +186,7 @@ class Models:
"received_payment",
self.metadata,
Column("received_payment_id", SLBigInteger, primary_key=True),
Column("created", TZDateTime,
server_default=func.now(), nullable=False),
Column("created_time_ms", SLBigInteger, nullable=False),
Column("squeak_hash", Binary(32), nullable=False),
Column("payment_hash", Binary(32), unique=True, nullable=False),
Column("price_msat", Integer, nullable=False),

View file

@ -20,10 +20,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import logging
import time
from contextlib import contextmanager
from datetime import datetime
from datetime import timedelta
from datetime import timezone
from typing import Iterator
from typing import List
from typing import Optional
@ -110,19 +108,19 @@ class SqueakDb:
@property
def squeak_is_liked(self):
return self.squeaks.c.liked_time != None # noqa: E711
return self.squeaks.c.liked_time_ms != None # noqa: E711
@property
def squeak_is_not_liked(self):
return self.squeaks.c.liked_time == None # noqa: E711
return self.squeaks.c.liked_time_ms == None # noqa: E711
@property
def squeak_has_no_secret_key(self):
return self.squeaks.c.secret_key == None # noqa: E711
def squeak_is_older_than_retention(self, interval_s):
return self.datetime_now - timedelta(seconds=interval_s) > \
self.squeaks.c.created
return self.timestamp_now_ms > \
self.squeaks.c.created_time_ms + interval_s * 1000
@property
def profile_has_private_key(self):
@ -141,18 +139,15 @@ class SqueakDb:
return self.received_offers.c.squeak_hash == None # noqa: E711
@property
def datetime_now(self):
return datetime.now(timezone.utc)
def datetime_from_timestamp(self, timestamp):
return datetime.fromtimestamp(timestamp, timezone.utc)
def timestamp_now_ms(self):
return int(time.time() * 1000)
def received_offer_should_be_deleted(self):
expire_time = (
self.received_offers.c.invoice_timestamp
+ self.received_offers.c.invoice_expiry
)
return self.datetime_now.timestamp() >= expire_time
return self.timestamp_now_ms / 1000 >= expire_time
@property
def received_offer_is_not_paid(self):
@ -164,14 +159,15 @@ class SqueakDb:
self.received_offers.c.invoice_timestamp
+ self.received_offers.c.invoice_expiry
)
return self.datetime_now.timestamp() < expire_time
return self.timestamp_now_ms / 1000 < expire_time
def sent_offer_should_be_deleted(self, interval_s):
expire_time = (
self.sent_offers.c.invoice_timestamp
+ self.sent_offers.c.invoice_expiry
+ interval_s
)
return self.datetime_now.timestamp() >= expire_time + interval_s
return self.timestamp_now_ms / 1000 >= expire_time
@property
def sent_offer_is_not_paid(self):
@ -183,7 +179,7 @@ class SqueakDb:
self.sent_offers.c.invoice_timestamp
+ self.sent_offers.c.invoice_expiry
)
return self.datetime_now.timestamp() < expire_time
return self.timestamp_now_ms / 1000 < expire_time
def insert_squeak(self, squeak: CSqueak, block_header: CBlockHeader) -> bytes:
""" Insert a new squeak.
@ -191,6 +187,7 @@ class SqueakDb:
Return the hash (bytes) of the inserted squeak.
"""
ins = self.squeaks.insert().values(
created_time_ms=self.timestamp_now_ms,
hash=get_hash(squeak),
squeak=squeak.serialize(),
hash_reply_sqk=squeak.hashReplySqk if squeak.is_reply else None,
@ -308,16 +305,15 @@ class SqueakDb:
last_entry: Optional[SqueakEntry],
) -> List[SqueakEntry]:
""" Get liked squeaks. """
last_liked_time = self.datetime_from_timestamp(
last_entry.liked_time) if last_entry else self.datetime_now
last_liked_time_ms = last_entry.liked_time_ms if last_entry else self.timestamp_now_ms
last_squeak_hash = last_entry.squeak_hash if last_entry else MAX_HASH
logger.info("""Liked squeaks db query with
limit: {}
last_liked_time: {}
last_liked_time_ms: {}
last_squeak_hash: {}
""".format(
limit,
last_liked_time,
last_liked_time_ms,
last_squeak_hash.hex(),
))
s = (
@ -333,15 +329,15 @@ class SqueakDb:
)
.where(
tuple_(
self.squeaks.c.liked_time,
self.squeaks.c.liked_time_ms,
self.squeaks.c.hash,
) < tuple_(
last_liked_time,
last_liked_time_ms,
last_squeak_hash,
)
)
.order_by(
self.squeaks.c.liked_time.desc(),
self.squeaks.c.liked_time_ms.desc(),
self.squeaks.c.hash.desc(),
)
.limit(limit)
@ -657,6 +653,7 @@ class SqueakDb:
def insert_profile(self, squeak_profile: SqueakProfile) -> int:
""" Insert a new squeak profile. """
ins = self.profiles.insert().values(
created_time_ms=self.timestamp_now_ms,
profile_name=squeak_profile.profile_name,
private_key=squeak_profile.private_key,
address=squeak_profile.address,
@ -823,7 +820,7 @@ class SqueakDb:
stmt = (
self.squeaks.update()
.where(self.squeaks.c.hash == squeak_hash)
.values(liked_time=self.datetime_now)
.values(liked_time_ms=self.timestamp_now_ms)
)
with self.get_connection() as connection:
connection.execute(stmt)
@ -833,7 +830,7 @@ class SqueakDb:
stmt = (
self.squeaks.update()
.where(self.squeaks.c.hash == squeak_hash)
.values(liked_time=None)
.values(liked_time_ms=None)
)
with self.get_connection() as connection:
connection.execute(stmt)
@ -849,6 +846,7 @@ class SqueakDb:
def insert_peer(self, squeak_peer: SqueakPeer) -> int:
""" Insert a new squeak peer. """
ins = self.peers.insert().values(
created_time_ms=self.timestamp_now_ms,
peer_name=squeak_peer.peer_name,
host=squeak_peer.address.host,
port=squeak_peer.address.port,
@ -916,6 +914,7 @@ class SqueakDb:
def insert_received_offer(self, received_offer: ReceivedOffer):
""" Insert a new received offer. """
ins = self.received_offers.insert().values(
created_time_ms=self.timestamp_now_ms,
squeak_hash=received_offer.squeak_hash,
payment_hash=received_offer.payment_hash,
nonce=received_offer.nonce,
@ -1028,6 +1027,7 @@ class SqueakDb:
def insert_sent_payment(self, sent_payment: SentPayment):
""" Insert a new sent payment. """
ins = self.sent_payments.insert().values(
created_time_ms=self.timestamp_now_ms,
peer_host=sent_payment.peer_address.host,
peer_port=sent_payment.peer_address.port,
squeak_hash=sent_payment.squeak_hash,
@ -1048,7 +1048,7 @@ class SqueakDb:
last_sent_payment: Optional[SentPayment],
) -> List[SentPayment]:
""" Get all sent payments. """
last_created_time = last_sent_payment.created if last_sent_payment else self.datetime_now
last_created_time = last_sent_payment.created_time_ms if last_sent_payment else self.timestamp_now_ms
last_payment_hash = last_sent_payment.payment_hash if last_sent_payment else MAX_HASH
logger.info("""Get sent payments db query with
limit: {}
@ -1063,7 +1063,7 @@ class SqueakDb:
select([self.sent_payments])
.where(
tuple_(
self.sent_payments.c.created,
self.sent_payments.c.created_time_ms,
self.sent_payments.c.payment_hash,
) < tuple_(
last_created_time,
@ -1071,7 +1071,7 @@ class SqueakDb:
)
)
.order_by(
self.sent_payments.c.created.desc(),
self.sent_payments.c.created_time_ms.desc(),
self.sent_payments.c.payment_hash.desc(),
)
.limit(limit)
@ -1099,6 +1099,7 @@ class SqueakDb:
def insert_sent_offer(self, sent_offer: SentOffer):
""" Insert a new sent offer. """
ins = self.sent_offers.insert().values(
created_time_ms=self.timestamp_now_ms,
squeak_hash=sent_offer.squeak_hash,
payment_hash=sent_offer.payment_hash,
secret_key=sent_offer.secret_key,
@ -1118,7 +1119,7 @@ class SqueakDb:
def get_sent_offers(self) -> List[SentOffer]:
""" Get all received payments. """
s = select([self.sent_offers]).order_by(
self.sent_offers.c.created.desc(),
self.sent_offers.c.created_time_ms.desc(),
)
with self.get_connection() as connection:
result = connection.execute(s)
@ -1204,6 +1205,7 @@ class SqueakDb:
def insert_received_payment(self, received_payment: ReceivedPayment):
""" Insert a new received payment. """
ins = self.received_payments.insert().values(
created_time_ms=self.timestamp_now_ms,
squeak_hash=received_payment.squeak_hash,
payment_hash=received_payment.payment_hash,
price_msat=received_payment.price_msat,
@ -1222,7 +1224,7 @@ class SqueakDb:
def get_received_payments(self) -> List[ReceivedPayment]:
""" Get all received payments. """
s = select([self.received_payments]).order_by(
self.received_payments.c.created.desc(),
self.received_payments.c.created_time_ms.desc(),
)
with self.get_connection() as connection:
result = connection.execute(s)
@ -1290,8 +1292,7 @@ class SqueakDb:
is_locked = bool(secret_key_column)
reply_to = (
row["hash_reply_sqk"]) if row["hash_reply_sqk"] else None
liked_time = row["liked_time"]
liked_time_s = int(liked_time.timestamp()) if liked_time else None
liked_time_ms = row["liked_time_ms"]
profile = self._try_parse_squeak_profile(row)
return SqueakEntry(
squeak_hash=(row["hash"]),
@ -1302,7 +1303,7 @@ class SqueakDb:
squeak_time=row["n_time"],
reply_to=reply_to,
is_unlocked=is_locked,
liked_time=liked_time_s,
liked_time_ms=liked_time_ms,
content=row["content"],
squeak_profile=profile,
)
@ -1362,7 +1363,7 @@ class SqueakDb:
def _parse_sent_payment(self, row) -> SentPayment:
return SentPayment(
sent_payment_id=row["sent_payment_id"],
created=row[self.sent_payments.c.created],
created_time_ms=row[self.sent_payments.c.created_time_ms],
peer_address=PeerAddress(
host=row["peer_host"],
port=row["peer_port"],
@ -1395,7 +1396,7 @@ class SqueakDb:
def _parse_received_payment(self, row) -> ReceivedPayment:
return ReceivedPayment(
received_payment_id=row["received_payment_id"],
created=row["created"],
created_time_ms=row["created_time_ms"],
squeak_hash=(row["squeak_hash"]),
payment_hash=(row["payment_hash"]),
price_msat=row["price_msat"],