kopia lustrzana https://github.com/bugout-dev/moonstream
249 wiersze
8.1 KiB
Python
249 wiersze
8.1 KiB
Python
import argparse
|
|
import json
|
|
import logging
|
|
import uuid
|
|
from typing import List, cast
|
|
|
|
import requests # type: ignore
|
|
from bugout.data import BugoutSearchResult
|
|
|
|
from ..settings import (
|
|
MOONSTREAM_ADMIN_ACCESS_TOKEN,
|
|
MOONSTREAM_API_URL,
|
|
MOONSTREAM_ENGINE_URL,
|
|
MOONSTREAM_LEADERBOARD_GENERATOR_BATCH_SIZE,
|
|
MOONSTREAM_LEADERBOARD_GENERATOR_JOURNAL_ID,
|
|
MOONSTREAM_LEADERBOARD_GENERATOR_PUSH_TIMEOUT_SECONDS,
|
|
)
|
|
from ..settings import bugout_client as bc
|
|
from .utils import get_results_for_moonstream_query, leaderboard_push_batch
|
|
|
|
logger = logging.getLogger(__name__)
|
|
logger.setLevel(logging.INFO)
|
|
|
|
blue_c = "\033[94m"
|
|
green_c = "\033[92m"
|
|
end_c = "\033[0m"
|
|
|
|
|
|
def handle_leaderboards(args: argparse.Namespace) -> None:
|
|
"""
|
|
Run the leaderboard generator.
|
|
|
|
Get query from journal and push results to leaderboard API.
|
|
"""
|
|
|
|
### get leaderboard journal
|
|
|
|
leaderboard_push_batch_size = args.leaderboard_push_batch_size
|
|
|
|
leaderboard_push_timeout_seconds = args.leaderboard_push_timeout_seconds
|
|
|
|
query = "#leaderboard #status:active"
|
|
|
|
if args.leaderboard_id: # way to run only one leaderboard without status:active
|
|
query = f"#leaderboard #leaderboard_id:{args.leaderboard_id}"
|
|
|
|
try:
|
|
leaderboards = bc.search(
|
|
token=MOONSTREAM_ADMIN_ACCESS_TOKEN,
|
|
journal_id=MOONSTREAM_LEADERBOARD_GENERATOR_JOURNAL_ID,
|
|
query=query,
|
|
limit=100,
|
|
timeout=10,
|
|
)
|
|
leaderboards_results = cast(List[BugoutSearchResult], leaderboards.results)
|
|
except Exception as e:
|
|
logger.error(f"Could not get leaderboards from journal: {e}")
|
|
return
|
|
|
|
if len(leaderboards_results) == 0:
|
|
logger.error("No leaderboard found")
|
|
return
|
|
|
|
logger.info(f"Found {len(leaderboards_results)} leaderboards")
|
|
|
|
for leaderboard in leaderboards_results:
|
|
logger.info(
|
|
f"Processing leaderboard: {leaderboard.title} with id: {[tag for tag in leaderboard.tags if tag.startswith('leaderboard_id')]}"
|
|
)
|
|
|
|
if leaderboard.content is None:
|
|
continue
|
|
|
|
try:
|
|
leaderboard_data = json.loads(leaderboard.content)
|
|
except json.JSONDecodeError:
|
|
logger.error(
|
|
f"Could not parse leaderboard content: {[tag for tag in leaderboard.tags if tag.startswith('leaderboard_id')]} in entry {leaderboard.entry_url.split('/')[-1]}"
|
|
)
|
|
continue
|
|
|
|
### get results from query API
|
|
|
|
leaderboard_id = leaderboard_data["leaderboard_id"]
|
|
|
|
query_name = leaderboard_data["query_name"]
|
|
|
|
if args.params:
|
|
params = json.loads(args.params)
|
|
else:
|
|
params = leaderboard_data["params"]
|
|
|
|
blockchain = leaderboard_data.get("blockchain", None)
|
|
|
|
### execute query
|
|
try:
|
|
query_results = get_results_for_moonstream_query(
|
|
args.query_api_access_token,
|
|
query_name,
|
|
params,
|
|
blockchain,
|
|
MOONSTREAM_API_URL,
|
|
args.max_retries,
|
|
args.interval,
|
|
args.query_api_retries,
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Could not get results for query {query_name}: error: {e}")
|
|
continue
|
|
|
|
### push results to leaderboard API
|
|
|
|
if query_results is None:
|
|
logger.error(f"Could not get results for query {query_name} in time")
|
|
continue
|
|
|
|
leaderboard_push_api_url = f"{MOONSTREAM_ENGINE_URL}/leaderboard/{leaderboard_id}/scores?normalize_addresses={leaderboard_data['normalize_addresses']}&overwrite=true"
|
|
|
|
leaderboard_api_headers = {
|
|
"Authorization": f"Bearer {args.query_api_access_token}",
|
|
"Content-Type": "application/json",
|
|
}
|
|
|
|
if len(query_results["data"]) > leaderboard_push_batch_size:
|
|
logger.info(
|
|
f"Pushing {len(query_results['data'])} scores to leaderboard {leaderboard_id} in batches of {leaderboard_push_batch_size}"
|
|
)
|
|
leaderboard_push_batch(
|
|
leaderboard_id,
|
|
leaderboard_data,
|
|
query_results["data"],
|
|
leaderboard_api_headers,
|
|
leaderboard_push_batch_size,
|
|
timeout=leaderboard_push_timeout_seconds,
|
|
)
|
|
|
|
else:
|
|
try:
|
|
leaderboard_api_response = requests.put(
|
|
leaderboard_push_api_url,
|
|
json=query_results["data"],
|
|
headers=leaderboard_api_headers,
|
|
timeout=leaderboard_push_timeout_seconds,
|
|
)
|
|
leaderboard_api_response.raise_for_status()
|
|
except requests.exceptions.HTTPError as http_error:
|
|
logger.error(
|
|
f"Could not push results to leaderboard API: {http_error.response.text} with status code {http_error.response.status_code}"
|
|
)
|
|
continue
|
|
|
|
### get leaderboard from leaderboard API
|
|
|
|
leaderboard_api_info_url = (
|
|
f"{MOONSTREAM_ENGINE_URL}/leaderboard/info?leaderboard_id={leaderboard_id}"
|
|
)
|
|
|
|
leaderboard_api_response = requests.get(
|
|
leaderboard_api_info_url, headers=leaderboard_api_headers, timeout=10
|
|
)
|
|
|
|
try:
|
|
leaderboard_api_response.raise_for_status()
|
|
except requests.exceptions.HTTPError as http_error:
|
|
logger.error(
|
|
f"Could not get leaderboard info from leaderboard API: {http_error.response.text} with status code {http_error.response.status_code}"
|
|
)
|
|
continue
|
|
|
|
info = leaderboard_api_response.json()
|
|
|
|
logger.info(
|
|
f"Successfully pushed results to leaderboard {info['id']}:{blue_c} {info['title']} {end_c}"
|
|
)
|
|
logger.info(
|
|
f"can be check on:{green_c} {MOONSTREAM_ENGINE_URL}/leaderboard/?leaderboard_id={leaderboard_id} {end_c}"
|
|
)
|
|
|
|
|
|
def main():
|
|
"""
|
|
CLI for generating leaderboards from Moonstream Query API
|
|
"""
|
|
|
|
parser = argparse.ArgumentParser(description="The Judge: Generate leaderboards")
|
|
parser.set_defaults(func=lambda _: parser.print_help())
|
|
subparsers = parser.add_subparsers()
|
|
|
|
leaderboard_generator_parser = subparsers.add_parser(
|
|
"leaderboards-generate", description="Generate Leaderboard"
|
|
)
|
|
leaderboard_generator_parser.add_argument(
|
|
"--leaderboard-id",
|
|
type=uuid.UUID,
|
|
required=False,
|
|
help="Leaderboard ID on Engine API",
|
|
)
|
|
leaderboard_generator_parser.add_argument(
|
|
"--max-retries",
|
|
type=int,
|
|
default=12,
|
|
help="Number of times to retry requests for Moonstream Query results",
|
|
)
|
|
leaderboard_generator_parser.add_argument(
|
|
"--query-api-retries",
|
|
type=int,
|
|
default=3,
|
|
help="Number of times to retry updating Moonstream Query data",
|
|
)
|
|
leaderboard_generator_parser.add_argument(
|
|
"--interval",
|
|
type=float,
|
|
default=10.0,
|
|
help="Number of seconds to wait between attempts to get results from Moonstream Query API",
|
|
)
|
|
leaderboard_generator_parser.add_argument(
|
|
"--params",
|
|
type=json.loads,
|
|
required=False,
|
|
help="Parameters to pass to Moonstream Query API. Use together with --leaderboard-id",
|
|
)
|
|
leaderboard_generator_parser.add_argument(
|
|
"--query-api-access-token",
|
|
type=str,
|
|
required=True,
|
|
help="Moonstream Access Token to use for Moonstream Query API requests",
|
|
)
|
|
leaderboard_generator_parser.add_argument(
|
|
"--leaderboard-push-batch-size",
|
|
type=int,
|
|
default=MOONSTREAM_LEADERBOARD_GENERATOR_BATCH_SIZE,
|
|
help="Number of scores to push to leaderboard API at once",
|
|
)
|
|
leaderboard_generator_parser.add_argument(
|
|
"--leaderboard-push-timeout-seconds",
|
|
type=int,
|
|
default=MOONSTREAM_LEADERBOARD_GENERATOR_PUSH_TIMEOUT_SECONDS,
|
|
help="Timeout for leaderboard API requests",
|
|
)
|
|
|
|
leaderboard_generator_parser.set_defaults(func=handle_leaderboards)
|
|
|
|
args = parser.parse_args()
|
|
args.func(args)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|