JoshCap20 / areion

The fastest Python web server. A lightweight, fast, and extensible asynchronous Python web server framework.
MIT License
0 stars 1 forks source link

Fix logger bug in Orchestrator #47

Closed JoshCap20 closed 1 month ago

JoshCap20 commented 1 month ago

Stacktrace:

(.venv) joshcaponigro@Joshs-MBP AreionTest % python advanced_example.py
Traceback (most recent call last):
  File "/Users/joshcaponigro/Documents/Coding/Arion/AreionTest/advanced_example.py", line 125, in <module>
    orchestrator.schedule_cron_task(scheduled_cleanup_task, {"minute": "0"})
  File "/Users/joshcaponigro/Documents/Coding/Arion/AreionSource/areion/default/orchestrator.py", line 49, in schedule_cron_task
    self.logger.info(
    ^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'info'

Code ran:

# advanced_example.py

import logging
from areion import (
    AreionServerBuilder,
    DefaultOrchestrator,
    DefaultEngine,
    DefaultLogger,
    DefaultRouter,
    HttpResponse,
    NotFoundError,
)

# Initialize the router
router = DefaultRouter()

# Initialize the logger
logger = DefaultLogger(log_file="server.log", log_level=logging.DEBUG)

# Initialize the template engine
engine = DefaultEngine(templates_dir="templates")

# Initialize the orchestrator
orchestrator = DefaultOrchestrator(max_workers=4)

# Global Middleware
def request_logger_middleware(handler):
    def wrapper(request, *args, **kwargs):
        request.log(f"Received request: {request.method} {request.path}", level="info")
        return handler(request, *args, **kwargs)

    return wrapper

router.add_global_middleware(request_logger_middleware)

# Route-specific Middleware
def auth_middleware(handler):
    def wrapper(request, *args, **kwargs):
        auth_header = request.get_header("Authorization")
        if not auth_header or auth_header != "Bearer secret-token":
            return HttpResponse(status_code=401, body="Unauthorized")
        return handler(request, *args, **kwargs)

    return wrapper

# Grouping Routes with Middleware
api_group = router.group("/api", middlewares=[auth_middleware])

# Dynamic Route with Template Rendering
@router.route("/user/:id", methods=["GET"])
def get_user(request, id):
    # Simulate fetching user data
    user_data = {"id": id, "name": f"User {id}", "email": f"user{id}@example.com"}
    return request.render_template("user_profile.html", user_data)

# Handling Exceptions
@router.route("/item/:item_id", methods=["GET"])
def get_item(request, item_id):
    # Simulate item retrieval
    item = None  # Suppose item is not found
    if not item:
        raise NotFoundError(f"Item with ID {item_id} not found")
    return item

# Route with Orchestrator Task Submission
@router.route("/process", methods=["POST"])
def process_data(request):
    def background_task(data):
        # Simulate long-running task
        import time

        time.sleep(5)
        logger.info(f"Processed data: {data}")

    # Simulate getting data from request
    data = {"key": "value"}
    request.submit_task(background_task, data)
    return "Data processing started"

# API Routes within Group
@api_group.route("/users", methods=["GET"])
def api_get_users(request):
    # Simulate fetching users
    users = [{"id": 1, "name": "User 1"}, {"id": 2, "name": "User 2"}]
    return {"users": users}

@api_group.route("/users", methods=["POST"])
def api_create_user(request):
    # Simulate user creation
    new_user = {"id": 3, "name": "User 3"}
    # Use a HttpResponse to modify status codes, default is 200 on success
    return HttpResponse(status_code=201, body=new_user)

# Traditional Route Definitions
def home_handler(request):
    return "Welcome to the Areion Server"

router.add_route("/", home_handler, methods=["GET"])

# Static File Serving
# Ensure you have a 'static' directory with the necessary files
static_dir = "static"

# Scheduled Task with Orchestrator
def scheduled_cleanup_task():
    print("Running scheduled cleanup task")
    # Simulate cleanup operations
    pass

# Schedule the cleanup task to run every hour
orchestrator.schedule_cron_task(scheduled_cleanup_task, {"minute": "0"})

# Build and run the server
server = (
    AreionServerBuilder()
    .with_host("0.0.0.0")
    .with_port(8080)
    .with_router(router)
    .with_logger(logger)
    .with_engine(engine)
    .with_orchestrator(orchestrator)
    .with_static_dir(static_dir)
    .build()
)

if __name__ == "__main__":
    server.run()

Will fix soon, time to play rocket league tho

JoshCap20 commented 1 month ago

Quick debug shows its because schedule cron task is called before the builder injects orchestrator with a logger.

Hmmm how to design this. Should the user just define certain logger characteristics and every core class has their own logger?