Update edge-api systemd service paths, switch to SQLite, add timezone-aware datetimes, and make job payments optional for proof-of-concept
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Waiting to run
Production Tests / Production Integration Tests (push) Waiting to run
Coverage Phase 1 (70% Target) / test-coverage-70 (push) Has been cancelled
Coverage Phase 2 (85% Target) / test-coverage-85 (push) Has been cancelled
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Integration Tests / test-service-integration (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
Some checks failed
API Endpoint Tests / test-api-endpoints (push) Waiting to run
Production Tests / Production Integration Tests (push) Waiting to run
Coverage Phase 1 (70% Target) / test-coverage-70 (push) Has been cancelled
Coverage Phase 2 (85% Target) / test-coverage-85 (push) Has been cancelled
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Integration Tests / test-service-integration (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Python Tests / test-python (push) Has been cancelled
Security Scanning / security-scan (push) Has been cancelled
This commit is contained in:
@@ -4,17 +4,18 @@ After=network.target postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=/opt/aitbc/apps/edge-api
|
||||
WorkingDirectory=/opt/aitbc/apps/aitbc-edge
|
||||
Environment="PATH=/opt/aitbc/venv/bin"
|
||||
Environment="PYTHONPATH=/opt/aitbc/packages/py/aitbc-core/src:/opt/aitbc/apps/edge-api/src:/opt/aitbc"
|
||||
Environment="DATABASE_URL=postgresql+asyncpg://aitbc_edge:password@localhost:5432/aitbc_edge"
|
||||
Environment="PYTHONPATH=/opt/aitbc/packages/py/aitbc-core/src:/opt/aitbc/apps/aitbc-edge/src:/opt/aitbc"
|
||||
Environment="DATABASE_URL=sqlite+aiosqlite:///opt/aitbc/data/edge.db"
|
||||
Environment="DATA_DIR=/opt/aitbc/data"
|
||||
Environment="BLOCKCHAIN_RPC_HOST=localhost"
|
||||
Environment="BLOCKCHAIN_RPC_PORT=8006"
|
||||
Environment="GPU_SERVICE_HOST=localhost"
|
||||
Environment="GPU_SERVICE_PORT=8101"
|
||||
Environment="JWT_SECRET_KEY=CQNLjrtnUVGzdO1skuLsxoiPEEmav2Vj3aA302cvo8I"
|
||||
Environment="API_PORT=8103"
|
||||
ExecStart=/opt/aitbc/venv/bin/python -m edge_api.main
|
||||
ExecStart=/opt/aitbc/venv/bin/python -m aitbc_edge.main
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Island-related schemas for Edge API Service"""
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from enum import StrEnum
|
||||
from uuid import uuid4
|
||||
|
||||
from sqlalchemy import JSON, Column, Enum as SQLEnum
|
||||
from sqlalchemy import JSON, Column, Enum as SQLEnum, String
|
||||
from sqlmodel import Field, SQLModel
|
||||
|
||||
|
||||
@@ -18,37 +18,37 @@ class IslandStatus(StrEnum):
|
||||
|
||||
class IslandMembership(SQLModel, table=True):
|
||||
"""Island membership in edge API database"""
|
||||
|
||||
|
||||
__tablename__ = "island_memberships"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
|
||||
id: str = Field(default_factory=lambda: f"membership_{uuid4().hex[:8]}", primary_key=True)
|
||||
island_id: str = Field(sa_column=Column(index=True))
|
||||
island_name: str
|
||||
chain_id: str = Field(sa_column=Column(index=True))
|
||||
island_id: str = Field(sa_column=Column(String, index=True))
|
||||
island_name: str = Field(sa_column=Column(String))
|
||||
chain_id: str = Field(sa_column=Column(String, index=True))
|
||||
status: IslandStatus = Field(
|
||||
default=IslandStatus.ACTIVE,
|
||||
sa_column=Column(SQLEnum(IslandStatus, values_only=True), index=True)
|
||||
)
|
||||
role: str = Field(default="compute-provider") # compute-provider, consumer, hub
|
||||
joined_at: datetime = Field(default_factory=lambda: datetime.utcnow())
|
||||
role: str = Field(default="compute-provider", sa_column=Column(String)) # compute-provider, consumer, hub
|
||||
joined_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
peer_count: int = Field(default=0)
|
||||
|
||||
|
||||
# Additional metadata
|
||||
extra_data: dict = Field(default_factory=dict, sa_column=Column(JSON, nullable=True))
|
||||
|
||||
|
||||
class BridgeRequest(SQLModel, table=True):
|
||||
"""Bridge request for island connectivity"""
|
||||
|
||||
|
||||
__tablename__ = "bridge_requests"
|
||||
__table_args__ = {"extend_existing": True}
|
||||
|
||||
|
||||
id: str = Field(default_factory=lambda: f"bridge_req_{uuid4().hex[:8]}", primary_key=True)
|
||||
request_id: str = Field(index=True)
|
||||
source_island_id: str
|
||||
target_island_id: str
|
||||
source_node_id: str
|
||||
status: str = Field(default="pending", index=True) # pending, approved, rejected
|
||||
created_at: datetime = Field(default_factory=lambda: datetime.utcnow())
|
||||
updated_at: datetime = Field(default_factory=lambda: datetime.utcnow())
|
||||
request_id: str = Field(sa_column=Column(String, index=True))
|
||||
source_island_id: str = Field(sa_column=Column(String))
|
||||
target_island_id: str = Field(sa_column=Column(String))
|
||||
source_node_id: str = Field(sa_column=Column(String))
|
||||
status: str = Field(default="pending", sa_column=Column(String, index=True)) # pending, approved, rejected
|
||||
created_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
updated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
|
||||
|
||||
@@ -12,7 +12,15 @@ from aitbc import get_logger
|
||||
logger = get_logger(__name__)
|
||||
|
||||
# Database URL from environment variable or default
|
||||
DATABASE_URL = os.getenv("DATABASE_URL", "postgresql+asyncpg://aitbc_edge:password@localhost:5432/aitbc_edge")
|
||||
DATABASE_URL = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///opt/aitbc/data/edge.db")
|
||||
|
||||
# Ensure data directory exists
|
||||
if DATABASE_URL.startswith("sqlite"):
|
||||
db_path = DATABASE_URL.replace("sqlite+aiosqlite:///", "").split("?")[0]
|
||||
db_dir = os.path.dirname(db_path)
|
||||
if db_dir and not os.path.exists(db_dir):
|
||||
os.makedirs(db_dir, exist_ok=True)
|
||||
logger.info(f"Created database directory: {db_dir}")
|
||||
|
||||
# Create async engine with proper connection pool settings
|
||||
engine = create_async_engine(
|
||||
|
||||
@@ -34,20 +34,28 @@ async def submit_job(
|
||||
service = JobService(session)
|
||||
job = service.create_job(client_id, req)
|
||||
|
||||
# Create payment if amount is specified
|
||||
# Create payment if amount is specified (optional for proof-of-concept)
|
||||
if req.payment_amount and req.payment_amount > 0:
|
||||
payment_service = PaymentService(session)
|
||||
payment_create = JobPaymentCreate(
|
||||
job_id=job.id,
|
||||
amount=req.payment_amount,
|
||||
currency=req.payment_currency,
|
||||
payment_method="aitbc_token", # Jobs use AITBC tokens
|
||||
)
|
||||
payment = await payment_service.create_payment(job.id, payment_create)
|
||||
job.payment_id = payment.id
|
||||
job.payment_status = payment.status
|
||||
session.commit()
|
||||
session.refresh(job)
|
||||
try:
|
||||
payment_service = PaymentService(session)
|
||||
payment_create = JobPaymentCreate(
|
||||
job_id=job.id,
|
||||
amount=req.payment_amount,
|
||||
currency=req.payment_currency,
|
||||
payment_method="aitbc_token", # Jobs use AITBC tokens
|
||||
)
|
||||
payment = await payment_service.create_payment(job.id, payment_create)
|
||||
job.payment_id = payment.id
|
||||
job.payment_status = payment.status
|
||||
session.commit()
|
||||
session.refresh(job)
|
||||
logger.info(f"Payment created for job {job.id}: {payment.id}")
|
||||
except Exception as e:
|
||||
# Payment creation failure should not block job submission for proof-of-concept
|
||||
logger.warning(f"Payment creation failed for job {job.id}, proceeding without payment: {e}")
|
||||
job.payment_status = "skipped"
|
||||
session.commit()
|
||||
session.refresh(job)
|
||||
|
||||
return service.to_view(job) # type: ignore[no-any-return]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user