startup errors fix #2
This commit is contained in:
parent
4cca40a626
commit
79165b49b5
|
|
@ -31,7 +31,7 @@ _now_str = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
|
||||||
LOG_FILEPATH = f"{LOG_DIR}/{_now_str}.log"
|
LOG_FILEPATH = f"{LOG_DIR}/{_now_str}.log"
|
||||||
|
|
||||||
WEB_APP_URLS = {
|
WEB_APP_URLS = {
|
||||||
'uploadContent': f"https://web2-client.vercel.app/uploadContent"
|
'uploadContent': f"https://my-public-node-8.projscale.dev/uploadContent"
|
||||||
}
|
}
|
||||||
|
|
||||||
ALLOWED_CONTENT_TYPES = [
|
ALLOWED_CONTENT_TYPES = [
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
from os import getenv, urandom
|
from os import getenv, urandom
|
||||||
import os
|
import os
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
from nacl.bindings import crypto_sign_seed_keypair
|
from nacl.bindings import crypto_sign_seed_keypair
|
||||||
from tonsdk.utils import Address
|
from tonsdk.utils import Address
|
||||||
|
|
||||||
from app.core._blockchain.ton.wallet_v3cr3 import WalletV3CR3
|
from app.core._blockchain.ton.wallet_v3cr3 import WalletV3CR3
|
||||||
from app.core.logger import make_log
|
from app.core.logger import make_log
|
||||||
|
from sqlalchemy import create_engine, text
|
||||||
|
|
||||||
|
|
||||||
def _load_seed_from_env_or_generate() -> bytes:
|
def _load_seed_from_env_or_generate() -> bytes:
|
||||||
|
|
@ -17,13 +20,83 @@ def _load_seed_from_env_or_generate() -> bytes:
|
||||||
return urandom(32)
|
return urandom(32)
|
||||||
|
|
||||||
|
|
||||||
|
def _init_seed_via_db() -> bytes:
|
||||||
|
"""Store and read hot seed from PostgreSQL service_config (key='private_key').
|
||||||
|
Primary node writes it once; workers wait until it appears.
|
||||||
|
"""
|
||||||
|
from app.core._config import DATABASE_URL
|
||||||
|
|
||||||
|
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
|
||||||
|
role = os.getenv("NODE_ROLE", "worker").lower()
|
||||||
|
|
||||||
|
def db_ready(conn) -> bool:
|
||||||
|
try:
|
||||||
|
r = conn.execute(text("SELECT to_regclass('public.service_config')")).scalar()
|
||||||
|
return r is not None
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Wait for table to exist
|
||||||
|
start = time.time()
|
||||||
|
with engine.connect() as conn:
|
||||||
|
while not db_ready(conn):
|
||||||
|
time.sleep(0.5)
|
||||||
|
if time.time() - start > 120:
|
||||||
|
raise TimeoutError("service_config table not available")
|
||||||
|
|
||||||
|
def read_seed() -> bytes | None:
|
||||||
|
row = conn.execute(text("SELECT packed_value FROM service_config WHERE key = :k LIMIT 1"), {"k": "private_key"}).first()
|
||||||
|
if not row:
|
||||||
|
return None
|
||||||
|
packed = row[0] or {}
|
||||||
|
try:
|
||||||
|
# packed_value is JSON; ensure dict
|
||||||
|
if isinstance(packed, str):
|
||||||
|
packed = json.loads(packed)
|
||||||
|
seed_hex = packed.get("value")
|
||||||
|
return bytes.fromhex(seed_hex) if seed_hex else None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
seed = read_seed()
|
||||||
|
if seed:
|
||||||
|
return seed
|
||||||
|
|
||||||
|
if role == "primary":
|
||||||
|
seed = _load_seed_from_env_or_generate()
|
||||||
|
# Try insert; if another primary raced, ignore
|
||||||
|
try:
|
||||||
|
conn.execute(
|
||||||
|
text("INSERT INTO service_config (key, packed_value) VALUES (:k, CAST(:v AS JSON))"),
|
||||||
|
{"k": "private_key", "v": json.dumps({"value": seed.hex()})}
|
||||||
|
)
|
||||||
|
conn.commit()
|
||||||
|
make_log("HotWallet", "Seed saved in service_config by primary", level='info')
|
||||||
|
return seed
|
||||||
|
except Exception:
|
||||||
|
conn.rollback()
|
||||||
|
# Read again in case of race
|
||||||
|
seed2 = read_seed()
|
||||||
|
if seed2:
|
||||||
|
return seed2
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
make_log("HotWallet", "Worker waiting for seed in service_config...", level='info')
|
||||||
|
while True:
|
||||||
|
seed = read_seed()
|
||||||
|
if seed:
|
||||||
|
return seed
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
|
||||||
_extra_ton_wallet_options = {}
|
_extra_ton_wallet_options = {}
|
||||||
if getenv('TON_CUSTOM_WALLET_ADDRESS'):
|
if getenv('TON_CUSTOM_WALLET_ADDRESS'):
|
||||||
_extra_ton_wallet_options['address'] = Address(getenv('TON_CUSTOM_WALLET_ADDRESS'))
|
_extra_ton_wallet_options['address'] = Address(getenv('TON_CUSTOM_WALLET_ADDRESS'))
|
||||||
|
|
||||||
|
|
||||||
def _init_wallet():
|
def _init_wallet():
|
||||||
hot_seed_bytes = _load_seed_from_env_or_generate()
|
# Primary writes to DB; workers wait and read from DB
|
||||||
|
hot_seed_bytes = _init_seed_via_db()
|
||||||
pub, priv = crypto_sign_seed_keypair(hot_seed_bytes)
|
pub, priv = crypto_sign_seed_keypair(hot_seed_bytes)
|
||||||
wallet = WalletV3CR3(
|
wallet = WalletV3CR3(
|
||||||
private_key=priv,
|
private_key=priv,
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,11 @@ async def indexer_loop(memory, platform_found: bool, seqno: int) -> [bool, int]:
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
make_log("TON_Daemon", f"Error while saving TON per STAR price: {e}" + '\n' + traceback.format_exc(), level="ERROR")
|
make_log("TON_Daemon", f"Error while saving TON per STAR price: {e}" + '\n' + traceback.format_exc(), level="ERROR")
|
||||||
|
|
||||||
|
from sqlalchemy import cast
|
||||||
|
from sqlalchemy.dialects.postgresql import JSONB
|
||||||
new_licenses = (await session.execute(select(UserContent).where(
|
new_licenses = (await session.execute(select(UserContent).where(
|
||||||
and_(
|
and_(
|
||||||
~UserContent.meta.contains({'notification_sent': True}),
|
~(cast(UserContent.meta, JSONB).contains({'notification_sent': True})),
|
||||||
UserContent.type == 'nft/listen'
|
UserContent.type == 'nft/listen'
|
||||||
)
|
)
|
||||||
))).scalars().all()
|
))).scalars().all()
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ async def license_index_loop(memory, platform_found: bool, seqno: int) -> [bool,
|
||||||
User.last_use > datetime.now() - timedelta(hours=4)
|
User.last_use > datetime.now() - timedelta(hours=4)
|
||||||
).order_by(User.updated.asc()))).scalars().all()
|
).order_by(User.updated.asc()))).scalars().all()
|
||||||
for user in users:
|
for user in users:
|
||||||
user_wallet_address = user.wallet_address(session)
|
user_wallet_address = await user.wallet_address_async(session)
|
||||||
if not user_wallet_address:
|
if not user_wallet_address:
|
||||||
make_log("LicenseIndex", f"User {user.id} has no wallet address", level="info")
|
make_log("LicenseIndex", f"User {user.id} has no wallet address", level="info")
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ async def main_fn(memory):
|
||||||
service_wallet.create_transfer_message(
|
service_wallet.create_transfer_message(
|
||||||
[{
|
[{
|
||||||
'address': highload_wallet.address.to_string(1, 1, 0),
|
'address': highload_wallet.address.to_string(1, 1, 0),
|
||||||
'amount': int(0.08 * 10 ** 9),
|
'amount': int(0.02 * 10 ** 9),
|
||||||
'send_mode': 1,
|
'send_mode': 1,
|
||||||
'payload': begin_cell().store_uint(0, 32).end_cell()
|
'payload': begin_cell().store_uint(0, 32).end_cell()
|
||||||
}], sw_seqno_value
|
}], sw_seqno_value
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue