Skip to content

Commit

Permalink
feat: guvicorn support
Browse files Browse the repository at this point in the history
  • Loading branch information
g0ldyy committed Feb 27, 2025
1 parent f0d997e commit 6304079
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 27 deletions.
1 change: 1 addition & 0 deletions .env-sample
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ ADDON_NAME=Comet # for Stremio
FASTAPI_HOST=0.0.0.0
FASTAPI_PORT=8000
FASTAPI_WORKERS=1
USE_GUNICORN=True # will use uvicorn if False or if on Windows
DASHBOARD_ADMIN_PASSWORD=CHANGE_ME # The password to access the dashboard with active connections and soon more...
DATABASE_TYPE=sqlite # or postgresql if you're making a Comet cluster
DATABASE_URL=username:password@hostname:port # to connect to PostgreSQL
Expand Down
96 changes: 74 additions & 22 deletions comet/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import time
import traceback
import uvicorn
import os

from contextlib import asynccontextmanager

Expand Down Expand Up @@ -101,17 +102,6 @@ def signal_handler(sig, frame):
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

config = uvicorn.Config(
app,
host=settings.FASTAPI_HOST,
port=settings.FASTAPI_PORT,
proxy_headers=True,
forwarded_allow_ips="*",
workers=settings.FASTAPI_WORKERS,
log_config=None,
)
server = Server(config=config)


def start_log():
logger.log(
Expand Down Expand Up @@ -170,15 +160,77 @@ def start_log():
logger.log("COMET", f"Custom Header HTML: {bool(settings.CUSTOM_HEADER_HTML)}")


with server.run_in_thread():
def run_with_uvicorn():
"""Run the server with uvicorn only"""
config = uvicorn.Config(
app,
host=settings.FASTAPI_HOST,
port=settings.FASTAPI_PORT,
proxy_headers=True,
forwarded_allow_ips="*",
workers=settings.FASTAPI_WORKERS,
log_config=None,
)
server = Server(config=config)

with server.run_in_thread():
start_log()
try:
while True:
time.sleep(1) # Keep the main thread alive
except KeyboardInterrupt:
logger.log("COMET", "Server stopped by user")
except Exception as e:
logger.error(f"Unexpected error: {e}")
logger.exception(traceback.format_exc())
finally:
logger.log("COMET", "Server Shutdown")


def run_with_gunicorn():
"""Run the server with gunicorn and uvicorn workers"""
import gunicorn.app.base

class StandaloneApplication(gunicorn.app.base.BaseApplication):
def __init__(self, app, options=None):
self.options = options or {}
self.application = app
super().__init__()

def load_config(self):
config = {
key: value for key, value in self.options.items()
if key in self.cfg.settings and value is not None
}
for key, value in config.items():
self.cfg.set(key.lower(), value)

def load(self):
return self.application

workers = settings.FASTAPI_WORKERS
if workers <= 1:
workers = (os.cpu_count() or 1) * 2 + 1

options = {
"bind": f"{settings.FASTAPI_HOST}:{settings.FASTAPI_PORT}",
"workers": workers,
"worker_class": "uvicorn.workers.UvicornWorker",
"timeout": 120,
"keepalive": 5,
"preload_app": True,
"proxy_protocol": True,
"forwarded_allow_ips": "*",
}

start_log()
try:
while True:
time.sleep(1) # Keep the main thread alive
except KeyboardInterrupt:
logger.log("COMET", "Server stopped by user")
except Exception as e:
logger.error(f"Unexpected error: {e}")
logger.exception(traceback.format_exc())
finally:
logger.log("COMET", "Server Shutdown")
logger.log("COMET", f"Starting with gunicorn using {workers} workers")

StandaloneApplication(app, options).run()


if __name__ == "__main__":
if os.name == "nt" or not settings.USE_GUNICORN:
run_with_uvicorn()
else:
run_with_gunicorn()
1 change: 1 addition & 0 deletions comet/utils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class AppSettings(BaseSettings):
FASTAPI_HOST: Optional[str] = "0.0.0.0"
FASTAPI_PORT: Optional[int] = 8000
FASTAPI_WORKERS: Optional[int] = 1 # 2 * (os.cpu_count() or 1)
USE_GUNICORN: Optional[bool] = True
DASHBOARD_ADMIN_PASSWORD: Optional[str] = "".join(
random.choices(string.ascii_letters + string.digits, k=16)
)
Expand Down
13 changes: 8 additions & 5 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
volumes:
comet_data:

services:
comet:
container_name: comet
image: g0ldyy/comet
image: g0ldyy/comet:rewrite
restart: unless-stopped
ports:
- "8000:8000"
env_file:
- .env
volumes:
- comet_data:/data
- ./data:/data
healthcheck:
test: wget -qO- http://127.0.0.1:8000/health
interval: 30s
timeout: 10s
retries: 3
start_period: 20s
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies = [
"databases",
"demagnetize",
"fastapi",
"gunicorn",
"jinja2",
"loguru",
"mediaflow-proxy",
Expand Down

0 comments on commit 6304079

Please sign in to comment.