List metatx requesters with contracts and call requests calculated

pull/1124/head
kompotkot 2024-08-15 12:36:57 +00:00
rodzic 2b51aacf5e
commit 1c878329b0
5 zmienionych plików z 106 dodań i 9 usunięć

Wyświetl plik

@ -6,7 +6,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, Set, Tuple from typing import Any, Dict, List, Optional, Set, Tuple
from bugout.data import BugoutResourceHolder, BugoutResourceHolders, HolderType from bugout.data import BugoutResourceHolder, HolderType
from sqlalchemy import func, or_, text, tuple_ from sqlalchemy import func, or_, text, tuple_
from sqlalchemy.dialects.postgresql import insert from sqlalchemy.dialects.postgresql import insert
from sqlalchemy.engine import Row from sqlalchemy.engine import Row
@ -23,6 +23,7 @@ from .models import (
RegisteredContract, RegisteredContract,
) )
from .settings import ( from .settings import (
METATX_REQUESTER_TYPE,
MOONSTREAM_ADMIN_ACCESS_TOKEN, MOONSTREAM_ADMIN_ACCESS_TOKEN,
MOONSTREAM_APPLICATION_ID, MOONSTREAM_APPLICATION_ID,
bugout_client, bugout_client,
@ -186,7 +187,7 @@ def validate_method_and_params(
def create_resource_for_registered_contract(user_id: uuid.UUID) -> uuid.UUID: def create_resource_for_registered_contract(user_id: uuid.UUID) -> uuid.UUID:
resource_data = {"type": "metatx_requester"} resource_data = {"type": METATX_REQUESTER_TYPE}
creator_permissions = ["create", "read", "update", "delete"] creator_permissions = ["create", "read", "update", "delete"]
resource = bugout_client.create_resource( resource = bugout_client.create_resource(
@ -847,6 +848,66 @@ def fetch_metatx_requester_ids(token: uuid.UUID) -> List[uuid.UUID]:
return metatx_requester_ids return metatx_requester_ids
def count_contracts_and_requests_for_requester(
db_session: Session, metatx_requester_ids: List[uuid.UUID]
) -> List[data.MetatxRequestersResponse]:
registered_contracts_subquery = (
db_session.query(
RegisteredContract.metatx_requester_id,
func.count(RegisteredContract.id).label("registered_contracts_count"),
)
.filter(RegisteredContract.metatx_requester_id.in_(metatx_requester_ids))
.group_by(RegisteredContract.metatx_requester_id)
.subquery()
)
call_requests_subquery = (
db_session.query(
CallRequest.metatx_requester_id,
func.count(CallRequest.id).label("call_requests_count"),
)
.filter(CallRequest.metatx_requester_id.in_(metatx_requester_ids))
.group_by(CallRequest.metatx_requester_id)
.subquery()
)
query = db_session.query(
registered_contracts_subquery.c.metatx_requester_id,
registered_contracts_subquery.c.registered_contracts_count,
call_requests_subquery.c.call_requests_count,
).outerjoin(
call_requests_subquery,
registered_contracts_subquery.c.metatx_requester_id
== call_requests_subquery.c.metatx_requester_id,
)
results = query.all()
metatx_requesters: List[data.MetatxRequestersResponse] = []
for r in results:
metatx_requester_id = r[0]
metatx_requesters.append(
data.MetatxRequestersResponse(
metatx_requester_id=metatx_requester_id,
registered_contracts_count=r[1],
call_requests_count=r[2],
)
)
metatx_requester_ids.remove(metatx_requester_id)
# Add empty metatx requesters
for r_id in metatx_requester_ids:
metatx_requesters.append(
data.MetatxRequestersResponse(
metatx_requester_id=r_id,
registered_contracts_count=0,
call_requests_count=0,
)
)
return metatx_requesters
def handle_register(args: argparse.Namespace) -> None: def handle_register(args: argparse.Namespace) -> None:
""" """
Handles the register command. Handles the register command.

Wyświetl plik

@ -278,6 +278,12 @@ class RegisteredContractWithHoldersResponse(RegisteredContractResponse):
holders: List[RegisteredContractHolderResponse] = Field(default_factory=list) holders: List[RegisteredContractHolderResponse] = Field(default_factory=list)
class MetatxRequestersResponse(BaseModel):
metatx_requester_id: UUID
registered_contracts_count: int
call_requests_count: int
class CallSpecification(BaseModel): class CallSpecification(BaseModel):
caller: str caller: str
method: str method: str

Wyświetl plik

@ -11,7 +11,7 @@ from typing import Dict, List, Optional, Set, Tuple
from uuid import UUID from uuid import UUID
from bugout.data import BugoutResourceHolder, BugoutUser from bugout.data import BugoutResourceHolder, BugoutUser
from fastapi import BackgroundTasks, Body, Depends, FastAPI, Form, Path, Query, Request from fastapi import BackgroundTasks, Body, Depends, FastAPI, Path, Query, Request
from sqlalchemy.exc import NoResultFound from sqlalchemy.exc import NoResultFound
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from web3 import Web3 from web3 import Web3
@ -40,6 +40,10 @@ tags_metadata = [
"description": DESCRIPTION, "description": DESCRIPTION,
}, },
{"name": "requests", "description": "Call requests for registered contracts."}, {"name": "requests", "description": "Call requests for registered contracts."},
{
"name": "requesters",
"description": "Metatx requester represented by resource for registered contracts access.",
},
] ]
@ -304,6 +308,36 @@ async def delete_contract_route(
return parsed_registered_contract return parsed_registered_contract
@app.get(
"/requesters",
tags=["requesters"],
response_model=List[data.MetatxRequestersResponse],
)
async def list_metatx_requesters_route(
user_authorization: Tuple[BugoutUser, UUID] = Depends(request_user_auth),
db_session: Session = Depends(db.yield_db_read_only_session),
) -> List[data.MetatxRequestersResponse]:
"""
Get list of metatx requesters available to user.
Helps to track number of empty metatx requesters without registered contracts and call requests.
"""
_, token = user_authorization
try:
metatx_requester_ids = contracts_actions.fetch_metatx_requester_ids(token=token)
metatx_requesters = (
contracts_actions.count_contracts_and_requests_for_requester(
db_session=db_session, metatx_requester_ids=metatx_requester_ids
)
)
except Exception as err:
logger.error(repr(err))
raise EngineHTTPException(status_code=500)
return metatx_requesters
@app.get( @app.get(
"/contracts/{contract_id}/holders", "/contracts/{contract_id}/holders",
tags=["contracts"], tags=["contracts"],

Wyświetl plik

@ -3,16 +3,10 @@ import sys
import time import time
from typing import Any, Dict, List, Optional from typing import Any, Dict, List, Optional
from bugout.data import BugoutResourceHolder
from sqlalchemy.sql import delete, distinct, func, insert, update from sqlalchemy.sql import delete, distinct, func, insert, update
from .. import db, models from .. import db, models
from ..contracts_actions import create_resource_for_registered_contract from ..contracts_actions import create_resource_for_registered_contract
from ..settings import (
MOONSTREAM_ADMIN_ACCESS_TOKEN,
MOONSTREAM_APPLICATION_ID,
bugout_client,
)
def generate_handler(args: argparse.Namespace): def generate_handler(args: argparse.Namespace):

Wyświetl plik

@ -21,6 +21,8 @@ bugout_client = Bugout(brood_api_url=BUGOUT_BROOD_URL, spire_api_url=BUGOUT_SPIR
BUGOUT_MAX_CONCURRENT_REQUESTS = 4 BUGOUT_MAX_CONCURRENT_REQUESTS = 4
bugout_client_semaphore = threading.Semaphore(BUGOUT_MAX_CONCURRENT_REQUESTS) bugout_client_semaphore = threading.Semaphore(BUGOUT_MAX_CONCURRENT_REQUESTS)
METATX_REQUESTER_TYPE = "metatx_requester"
ENGINE_DEV_RAW = os.environ.get("ENGINE_DEV", "") ENGINE_DEV_RAW = os.environ.get("ENGINE_DEV", "")
ENGINE_DEV = True if ENGINE_DEV_RAW in {"1", "true", "yes", "t", "y"} else False ENGINE_DEV = True if ENGINE_DEV_RAW in {"1", "true", "yes", "t", "y"} else False