feat: optimize filtering for DMs

This commit is contained in:
Vlad Stan 2023-03-08 18:33:23 +02:00
parent bf670c3545
commit 69dcbcb002
7 changed files with 79 additions and 19 deletions

43
crud.py
View file

@ -318,8 +318,22 @@ async def delete_product(user_id: str, product_id: str) -> None:
async def create_order(user_id: str, o: Order) -> Order: async def create_order(user_id: str, o: Order) -> Order:
await db.execute( await db.execute(
f""" f"""
INSERT INTO nostrmarket.orders (user_id, id, event_id, event_created_at, pubkey, address, contact_data, extra_data, order_items, stall_id, invoice_id, total) INSERT INTO nostrmarket.orders (
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) user_id,
id,
event_id,
event_created_at,
merchant_public_key,
public_key,
address,
contact_data,
extra_data,
order_items,
stall_id,
invoice_id,
total
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(event_id) DO NOTHING ON CONFLICT(event_id) DO NOTHING
""", """,
( (
@ -327,7 +341,8 @@ async def create_order(user_id: str, o: Order) -> Order:
o.id, o.id,
o.event_id, o.event_id,
o.event_created_at, o.event_created_at,
o.pubkey, o.merchant_public_key,
o.public_key,
o.address, o.address,
json.dumps(o.contact.dict() if o.contact else {}), json.dumps(o.contact.dict() if o.contact else {}),
json.dumps(o.extra.dict()), json.dumps(o.extra.dict()),
@ -384,6 +399,17 @@ async def get_orders_for_stall(user_id: str, stall_id: str) -> List[Order]:
return [Order.from_row(row) for row in rows] return [Order.from_row(row) for row in rows]
async def get_last_order_time(public_key: str) -> int:
row = await db.fetchone(
"""
SELECT event_created_at FROM nostrmarket.orders
WHERE merchant_public_key = ? ORDER BY event_created_at DESC LIMIT 1
""",
(public_key,),
)
return row[0] if row else 0
async def update_order_paid_status(order_id: str, paid: bool) -> Optional[Order]: async def update_order_paid_status(order_id: str, paid: bool) -> Optional[Order]:
await db.execute( await db.execute(
f"UPDATE nostrmarket.orders SET paid = ? WHERE id = ?", f"UPDATE nostrmarket.orders SET paid = ? WHERE id = ?",
@ -457,3 +483,14 @@ async def get_direct_messages(merchant_id: str, public_key: str) -> List[DirectM
(merchant_id, public_key), (merchant_id, public_key),
) )
return [DirectMessage.from_row(row) for row in rows] return [DirectMessage.from_row(row) for row in rows]
async def get_last_direct_messages_time(public_key: str) -> int:
row = await db.fetchone(
"""
SELECT event_created_at FROM nostrmarket.direct_messages
WHERE public_key = ? ORDER BY event_created_at DESC LIMIT 1
""",
(public_key),
)
return row[0] if row else 0

View file

@ -79,7 +79,8 @@ async def m001_initial(db):
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
event_id TEXT, event_id TEXT,
event_created_at INTEGER NOT NULL, event_created_at INTEGER NOT NULL,
pubkey TEXT NOT NULL, public_key TEXT NOT NULL,
merchant_public_key TEXT NOT NULL,
contact_data TEXT NOT NULL DEFAULT '{empty_object}', contact_data TEXT NOT NULL DEFAULT '{empty_object}',
extra_data TEXT NOT NULL DEFAULT '{empty_object}', extra_data TEXT NOT NULL DEFAULT '{empty_object}',
order_items TEXT NOT NULL, order_items TEXT NOT NULL,

View file

@ -282,7 +282,8 @@ class PartialOrder(BaseModel):
id: str id: str
event_id: Optional[str] event_id: Optional[str]
event_created_at: Optional[int] event_created_at: Optional[int]
pubkey: str public_key: str
merchant_public_key: str
items: List[OrderItem] items: List[OrderItem]
contact: Optional[OrderContact] contact: Optional[OrderContact]
address: Optional[str] address: Optional[str]

View file

@ -54,7 +54,7 @@ async def create_new_order(
payment_hash, invoice = await create_invoice( payment_hash, invoice = await create_invoice(
wallet_id=wallet_id, wallet_id=wallet_id,
amount=round(total_amount), amount=round(total_amount),
memo=f"Order '{data.id}' for pubkey '{data.pubkey}'", memo=f"Order '{data.id}' for pubkey '{data.public_key}'",
extra={ extra={
"tag": "nostrmarket", "tag": "nostrmarket",
"order_id": data.id, "order_id": data.id,
@ -107,7 +107,7 @@ async def handle_order_paid(order_id: str, merchant_pubkey: str):
order_status.dict(), separators=(",", ":"), ensure_ascii=False order_status.dict(), separators=(",", ":"), ensure_ascii=False
) )
dm_event = merchant.build_dm_event(dm_content, order.pubkey) dm_event = merchant.build_dm_event(dm_content, order.public_key)
await publish_nostr_event(dm_event) await publish_nostr_event(dm_event)
except Exception as ex: except Exception as ex:
logger.warning(ex) logger.warning(ex)
@ -143,7 +143,12 @@ async def _handle_incoming_dms(
event: NostrEvent, merchant: Merchant, clear_text_msg: str event: NostrEvent, merchant: Merchant, clear_text_msg: str
): ):
dm_content = await _handle_dirrect_message( dm_content = await _handle_dirrect_message(
merchant.id, event.pubkey, event.id, event.created_at, clear_text_msg merchant.id,
merchant.public_key,
event.pubkey,
event.id,
event.created_at,
clear_text_msg,
) )
if dm_content: if dm_content:
dm_event = merchant.build_dm_event(dm_content, event.pubkey) dm_event = merchant.build_dm_event(dm_content, event.pubkey)
@ -166,17 +171,23 @@ async def _handle_outgoing_dms(
async def _handle_dirrect_message( async def _handle_dirrect_message(
merchant_id: str, from_pubkey: str, event_id: str, event_created_at: int, msg: str merchant_id: str,
merchant_public_key: str,
from_pubkey: str,
event_id: str,
event_created_at: int,
msg: str,
) -> Optional[str]: ) -> Optional[str]:
order, text_msg = order_from_json(msg) order, text_msg = order_from_json(msg)
try: try:
if order: if order:
order["pubkey"] = from_pubkey order["public_key"] = from_pubkey
order["merchant_public_key"] = merchant_public_key
order["event_id"] = event_id order["event_id"] = event_id
order["event_created_at"] = event_created_at order["event_created_at"] = event_created_at
return await _handle_new_order(PartialOrder(**order)) return await _handle_new_order(PartialOrder(**order))
else: else:
print("### text_msg", text_msg) print("### text_msg", text_msg, event_created_at, event_id)
dm = PartialDirectMessage( dm = PartialDirectMessage(
event_id=event_id, event_id=event_id,
event_created_at=event_created_at, event_created_at=event_created_at,

View file

@ -43,8 +43,8 @@
></q-checkbox> ></q-checkbox>
</q-td> </q-td>
<q-td key="pubkey" :props="props"> <q-td key="public_key" :props="props">
{{toShortId(props.row.pubkey)}} {{toShortId(props.row.public_key)}}
</q-td> </q-td>
<q-td key="time" :props="props"> {{formatDate(props.row.time)}} </q-td> <q-td key="time" :props="props"> {{formatDate(props.row.time)}} </q-td>
</q-tr> </q-tr>
@ -115,7 +115,7 @@
dense dense
readonly readonly
disabled disabled
v-model.trim="props.row.pubkey" v-model.trim="props.row.public_key"
type="text" type="text"
></q-input> ></q-input>
</div> </div>

View file

@ -9,7 +9,11 @@ from websocket import WebSocketApp
from lnbits.core.models import Payment from lnbits.core.models import Payment
from lnbits.tasks import register_invoice_listener from lnbits.tasks import register_invoice_listener
from .crud import get_public_keys_for_merchants from .crud import (
get_last_direct_messages_time,
get_last_order_time,
get_public_keys_for_merchants,
)
from .nostr.nostr_client import connect_to_nostrclient_ws from .nostr.nostr_client import connect_to_nostrclient_ws
from .services import handle_order_paid, process_nostr_message from .services import handle_order_paid, process_nostr_message
@ -68,9 +72,15 @@ async def subscribe_to_nostr_client(recieve_event_queue: Queue, send_req_queue:
async def wait_for_nostr_events(recieve_event_queue: Queue, send_req_queue: Queue): async def wait_for_nostr_events(recieve_event_queue: Queue, send_req_queue: Queue):
public_keys = await get_public_keys_for_merchants() public_keys = await get_public_keys_for_merchants()
for p in public_keys: for p in public_keys:
await send_req_queue.put( last_order_time = await get_last_order_time(p)
["REQ", f"direct-messages-in:{p}", {"kind": 4, "#p": [p]}] last_dm_time = await get_last_direct_messages_time(p)
) since = max(last_order_time, last_dm_time)
in_messages_filter = {"kind": 4, "#p": [p]}
if since != 0:
in_messages_filter["since"] = since
print("### in_messages_filter", in_messages_filter)
await send_req_queue.put(["REQ", f"direct-messages-in:{p}", in_messages_filter])
# await send_req_queue.put( # await send_req_queue.put(
# ["REQ", f"direct-messages-out:{p}", {"kind": 4, "authors": [p]}] # ["REQ", f"direct-messages-out:{p}", {"kind": 4, "authors": [p]}]
# ) # )

View file

@ -500,7 +500,7 @@ async def api_update_order_status(
data.paid = order.paid data.paid = order.paid
dm_content = json.dumps(data.dict(), separators=(",", ":"), ensure_ascii=False) dm_content = json.dumps(data.dict(), separators=(",", ":"), ensure_ascii=False)
dm_event = merchant.build_dm_event(dm_content, order.pubkey) dm_event = merchant.build_dm_event(dm_content, order.public_key)
await publish_nostr_event(dm_event) await publish_nostr_event(dm_event)
return order return order