1234
This commit is contained in:
+8
-176
@@ -6,12 +6,11 @@
|
||||
|
||||
DATE:
|
||||
|
||||
Create: Monday, 29th Sept., 2025
|
||||
Create: Tuesday, 30th Sept., 2025
|
||||
|
||||
OBJECTIVE:
|
||||
|
||||
To have a centralized Socket.IO app from where several namespaces can be registered. This is kind of like how
|
||||
you can have one Quart app and register several blueprints.
|
||||
Simple helper functions to work with the Socket.IO server process.
|
||||
|
||||
REFERENCES:
|
||||
|
||||
@@ -36,49 +35,14 @@ import sys
|
||||
sys.path.append(".")
|
||||
sys.path.append("..")
|
||||
|
||||
# System-level activities:
|
||||
import io
|
||||
import os
|
||||
import random
|
||||
|
||||
# My utils:
|
||||
from utils_v2.string import json
|
||||
from utils_v2.string import regex
|
||||
from utils_v2.system import files
|
||||
from utils_v2.date_time import date_time
|
||||
from utils_v2.database.async_mongo_v2 import AsyncMongo
|
||||
from utils_v2.queue.kafka.controllers.async_kafka import ConsumerKafka, get_ssl_context
|
||||
from utils_v2.cache.async_redis_cache_v3 import AsyncRedisCache
|
||||
from utils_v2.serialization.json_serializer import JSONSerializer
|
||||
|
||||
# To make HTTP calls:
|
||||
import httpx
|
||||
|
||||
# To work with date and time:
|
||||
import datetime
|
||||
import time
|
||||
|
||||
# Models:
|
||||
from models.core.user import CoreUserInfoModel
|
||||
from models.finstitutions.trading.ticks import TradingTick
|
||||
|
||||
# To work with SocketIO:
|
||||
import socket
|
||||
import socketio
|
||||
|
||||
# To maintain the app's state:
|
||||
from wsio_v2.app_state import AppState
|
||||
from wsio_v2.test.test_ns import TestNamespace
|
||||
from wsio_v2.test.echo import echo
|
||||
|
||||
# For asynchronous activities:
|
||||
import asyncio
|
||||
|
||||
# To work with various datatypes:
|
||||
from typing import List
|
||||
|
||||
# Debugging:
|
||||
from icecream import IceCreamDebugger
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
@@ -88,42 +52,7 @@ from icecream import IceCreamDebugger
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# A custom class to maintain the app's state:
|
||||
app_state = AppState()
|
||||
|
||||
# Debugging:
|
||||
app_state.printer = IceCreamDebugger(prefix = "WSIO | ", includeContext = True)
|
||||
app_state.no_context_printer = IceCreamDebugger(prefix = "WSIO | ", includeContext = False)
|
||||
|
||||
# To make API calls:
|
||||
app_state.http_client = httpx.AsyncClient(
|
||||
limits = httpx.Limits(
|
||||
max_connections = 100, # ............ Maximum number of connections allowed in the pool.
|
||||
max_keepalive_connections = 50, # ... Maximum number of connections that can be kept alive.
|
||||
),
|
||||
timeout = httpx.Timeout(
|
||||
pool = 120.0, # .... Time to wait for a free connection from the pool.
|
||||
connect = 2.5, # ... Time to wait for establishing a connection to the server.
|
||||
write = 10.0, # .... Time to wait for sending data.
|
||||
read = 9.9 # ....... Time to wait for receiving data.
|
||||
)
|
||||
)
|
||||
|
||||
# General:
|
||||
app_state.SERVER_HOSTNAME = str(socket.gethostname())
|
||||
app_state.ALLOWED_ORIGINS = []
|
||||
|
||||
# Namespaces:
|
||||
app_state.NAMESPACE_DEFAULT = "/"
|
||||
app_state.NAMESPACE_TEST = "/test"
|
||||
app_state.NAMESPACE_TICKS = "/ticks"
|
||||
app_state.NAMESPACE_ORDER_UPDATES = "/order-updates"
|
||||
|
||||
# Events:
|
||||
app_state.EVENT_CONNECT = "connect"
|
||||
app_state.EVENT_DISCONNECT = "disconnect"
|
||||
app_state.EVENT_ECHO = "echo"
|
||||
app_state.EVENT_TICKS = "ticks"
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
@@ -133,13 +62,7 @@ app_state.EVENT_TICKS = "ticks"
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
# For SocketIO:
|
||||
sio = socketio.AsyncServer(
|
||||
cors_allowed_origins = "*",
|
||||
async_mode = "asgi"
|
||||
)
|
||||
app = socketio.ASGIApp(sio)
|
||||
sio.register_namespace(TestNamespace("/test"))
|
||||
# --- Nothing Yet
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
@@ -149,7 +72,7 @@ sio.register_namespace(TestNamespace("/test"))
|
||||
# *****************************************************************************************************************
|
||||
|
||||
|
||||
def origin_is_allowed(origin: str) -> bool:
|
||||
def origin_is_allowed(origin: str, app_state: AppState) -> bool:
|
||||
|
||||
"""
|
||||
To check if a given origin is in the allowed list.
|
||||
@@ -182,7 +105,8 @@ def origin_is_allowed(origin: str) -> bool:
|
||||
|
||||
async def init(
|
||||
script_id: str,
|
||||
debug: bool
|
||||
debug: bool,
|
||||
app_state: AppState,
|
||||
):
|
||||
|
||||
"""
|
||||
@@ -192,12 +116,6 @@ async def init(
|
||||
:return: True if initialized successfully, else False.
|
||||
"""
|
||||
|
||||
# Declare the required global variables:
|
||||
# global SCRIPT_DATA
|
||||
# global ALLOWED_ORIGINS
|
||||
# global redis_cache
|
||||
# global kafka_consumer
|
||||
|
||||
# Basic stuff:
|
||||
if debug: app_state.printer.enable()
|
||||
app_state.printer("Initializing.")
|
||||
@@ -300,29 +218,6 @@ async def init(
|
||||
return True
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def register_namespaces():
|
||||
|
||||
"""
|
||||
A quick function that registers all the namespaces to the same Socket.IO app.
|
||||
"""
|
||||
|
||||
app_state.printer("Registering namespaces.")
|
||||
sio.register_namespace(TestNamespace("/test"))
|
||||
app_state.printer("Namespaces registered.")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@sio.on(event = app_state.EVENT_ECHO, namespace = app_state.NAMESPACE_DEFAULT)
|
||||
async def echo(sid, data):
|
||||
print(f"Received (default ns) from {sid}: {data}")
|
||||
await sio.emit("echo", data, to = sid)
|
||||
|
||||
|
||||
# *****************************************************************************************************************
|
||||
# ***** ****
|
||||
# *** MAIN PROGRAM ***
|
||||
@@ -332,67 +227,4 @@ async def echo(sid, data):
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
app_state.printer("Main.")
|
||||
|
||||
# To get args from the terminal:
|
||||
import argparse
|
||||
|
||||
# To run the ASGI:
|
||||
import uvicorn
|
||||
from multiprocessing import freeze_support
|
||||
|
||||
# Get the config from the command-line:
|
||||
parser = argparse.ArgumentParser(description = f"SocketIO to serve live market data (and a general passthrough).")
|
||||
parser.add_argument(
|
||||
"-w", "--workers",
|
||||
type = int,
|
||||
help = "The no. of threads to spin up for this instance!",
|
||||
default = 2
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a", "--host",
|
||||
type = str,
|
||||
help = "The host for the app. e.g.: '0.0.0.0' or '127.0.0.1'.",
|
||||
default = "0.0.0.0"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p", "--port",
|
||||
type = int,
|
||||
help = "The port no. to bind the app to.",
|
||||
default = 8080
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s", "--script-id",
|
||||
type = str,
|
||||
help = "The id of this script (will affect the loaded config)."
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d", "--debug",
|
||||
action = "store_true",
|
||||
help = "Whether, or not, you want to see debugging messages in the terminal.",
|
||||
default = False
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# Note down the config;
|
||||
os.environ["SCRIPT_ID"] = args.script_id
|
||||
os.environ["DEBUG"] = str(args.debug)
|
||||
|
||||
# Startup message:
|
||||
app_state.printer.enable()
|
||||
app_state.printer(str(args.debug))
|
||||
if str(args.debug).lower().find("false") >= 0: app_state.printer.disable()
|
||||
|
||||
# Register all namespaces:
|
||||
app_state.init_func = init
|
||||
app_state.origin_check_func = origin_is_allowed
|
||||
# register_namespaces()
|
||||
|
||||
# Run the gateway:
|
||||
freeze_support()
|
||||
uvicorn.run(
|
||||
app = "app:app",
|
||||
workers = args.workers,
|
||||
host = args.host,
|
||||
port = args.port
|
||||
)
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user