Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ hornbeam:start("main:app", #{worker_class => asgi}).

%% With all options
hornbeam:start("myapp:application", #{
bind => "0.0.0.0:8000",
workers => 4,
bind => <<"0.0.0.0:8642">>,
num_contexts => 4,
worker_class => asgi,
lifespan => auto
}).
Expand Down Expand Up @@ -220,7 +220,7 @@ rebar3 shell
```erlang
hornbeam:start("myapp:application", #{
%% Server
bind => <<"0.0.0.0:8000">>,
bind => <<"0.0.0.0:8642">>,
ssl => false,
certfile => undefined,
keyfile => undefined,
Expand All @@ -230,11 +230,12 @@ hornbeam:start("myapp:application", #{
%% 'HTTP/2' and 'HTTP/3' require ssl => true
http_version => ['HTTP/1.1'],

%% Workers
workers => 4,
%% Python contexts
num_contexts => 4, % defaults to the scheduler count
num_acceptors => 100,
max_concurrent => 10000,
timeout => 30000,
keepalive => 2,
max_requests => 1000,

%% ASGI
lifespan => auto, % auto | on | off
Expand All @@ -251,13 +252,14 @@ hornbeam:start("myapp:application", #{
### Via sys.config

```erlang
%% Every option defaults in hornbeam_config:defaults/0; set a key here
%% only to override one.
[
{hornbeam, [
{bind, "127.0.0.1:8000"},
{workers, 4},
{bind, <<"127.0.0.1:8642">>},
{worker_class, wsgi},
{timeout, 30000},
{pythonpath, ["."]}
{pythonpath, [<<".">>]}
]}
].
```
Expand Down
16 changes: 6 additions & 10 deletions config/sys.config
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
%% Every hornbeam option defaults in hornbeam_config:defaults/0. Set a
%% key here only to override one; `hornbeam_config:env_keys/0' lists
%% what is recognised, and an unknown key is ignored rather than
%% refused, which is why this file stays short.
[
{hornbeam, [
{bind, "127.0.0.1:8000"},
{workers, 4},
{bind, <<"127.0.0.1:8642">>},
{worker_class, wsgi},
{timeout, 30000},
{keepalive, 2},
{max_requests, 1000},
{preload_app, false},
{pythonpath, [".", "examples"]},
%% WSGI body streaming settings
{wsgi_body_chunk_size, 65536}, %% 64KB chunks
{wsgi_streaming_threshold, 65536} %% Stream if > 64KB
{pythonpath, [<<".">>, <<"examples">>]}
]},
{erlang_python, [
{num_contexts, 4},
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/channels-chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ function leaveRoom() {
hornbeam run examples/channels_chat:app
```

Open http://localhost:8000 in multiple browser windows to test.
Open http://localhost:8642 in multiple browser windows to test.

### With Docker

Expand Down
12 changes: 6 additions & 6 deletions docs/examples/embedding-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,30 +286,30 @@ hornbeam:start("app:app", #{

```bash
# Index documents
curl -X POST http://localhost:8000/index \
curl -X POST http://localhost:8642/index \
-H "Content-Type: application/json" \
-d '{"id": "1", "text": "Python is a programming language", "metadata": {"category": "tech"}}'

curl -X POST http://localhost:8000/index \
curl -X POST http://localhost:8642/index \
-H "Content-Type: application/json" \
-d '{"id": "2", "text": "Erlang is great for concurrent systems"}'

curl -X POST http://localhost:8000/index \
curl -X POST http://localhost:8642/index \
-H "Content-Type: application/json" \
-d '{"id": "3", "text": "Machine learning uses neural networks"}'

# Search
curl -X POST http://localhost:8000/search \
curl -X POST http://localhost:8642/search \
-H "Content-Type: application/json" \
-d '{"query": "programming languages", "top_k": 5}'

# Direct embedding
curl -X POST http://localhost:8000/embed \
curl -X POST http://localhost:8642/embed \
-H "Content-Type: application/json" \
-d '{"texts": ["Hello world", "How are you?"]}'

# Check stats
curl http://localhost:8000/stats
curl http://localhost:8642/stats
```

## Requirements
Expand Down
18 changes: 9 additions & 9 deletions docs/examples/fastapi-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,35 +323,35 @@ hornbeam:start("app:app", #{

```bash
# Health check
curl http://localhost:8000/health
curl http://localhost:8642/health

# Create items
curl -X POST http://localhost:8000/items/ \
curl -X POST http://localhost:8642/items/ \
-H "Content-Type: application/json" \
-d '{"name": "Laptop", "description": "High-performance laptop", "price": 999.99}'

curl -X POST http://localhost:8000/items/ \
curl -X POST http://localhost:8642/items/ \
-H "Content-Type: application/json" \
-d '{"name": "Phone", "description": "Smartphone with great camera", "price": 699.99}'

# List items
curl http://localhost:8000/items/
curl http://localhost:8642/items/

# Generate embedding
curl -X POST http://localhost:8000/embed \
curl -X POST http://localhost:8642/embed \
-H "Content-Type: application/json" \
-d '{"text": "high quality electronics"}'

# Semantic search
curl -X POST http://localhost:8000/search \
curl -X POST http://localhost:8642/search \
-H "Content-Type: application/json" \
-d '{"query": "computing device", "top_k": 2}'

# Stream events
curl http://localhost:8000/stream
curl http://localhost:8642/stream

# Metrics
curl http://localhost:8000/metrics
curl http://localhost:8642/metrics
```

### WebSocket Testing
Expand All @@ -361,7 +361,7 @@ import asyncio
import websockets

async def test_ws():
async with websockets.connect('ws://localhost:8000/ws') as ws:
async with websockets.connect('ws://localhost:8642/ws') as ws:
await ws.send('{"message": "Hello!"}')
response = await ws.recv()
print(response)
Expand Down
14 changes: 7 additions & 7 deletions docs/examples/flask-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -214,30 +214,30 @@ gunicorn app:application

```bash
# Create items
curl -X POST http://localhost:8000/api/items \
curl -X POST http://localhost:8642/api/items \
-H "Content-Type: application/json" \
-d '{"name": "Item 1", "description": "First item"}'

curl -X POST http://localhost:8000/api/items \
curl -X POST http://localhost:8642/api/items \
-H "Content-Type: application/json" \
-d '{"name": "Item 2", "description": "Second item"}'

# List items (first call - not cached)
curl http://localhost:8000/api/items
curl http://localhost:8642/api/items
# {"items": [...], "cached": false}

# List items (second call - cached)
curl http://localhost:8000/api/items
curl http://localhost:8642/api/items
# {"items": [...], "cached": true}

# Get single item
curl http://localhost:8000/api/items/1
curl http://localhost:8642/api/items/1

# Check metrics
curl http://localhost:8000/metrics
curl http://localhost:8642/metrics

# Test rate limiting
for i in {1..105}; do curl http://localhost:8000/api/limited; done
for i in {1..105}; do curl http://localhost:8642/api/limited; done
```

## Requirements
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/websocket-chat.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ hornbeam:start("app:application", #{
}).
```

Open http://localhost:8000 in multiple browsers to test.
Open http://localhost:8642 in multiple browsers to test.

## Features

Expand Down
4 changes: 2 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ hornbeam:start("myapp:application").
### 3. Test It

```bash
curl http://localhost:8000
curl http://localhost:8642
# Hello from Hornbeam!
```

Expand Down Expand Up @@ -140,7 +140,7 @@ Basic configuration options:
```erlang
hornbeam:start("myapp:application", #{
%% Server binding
bind => "0.0.0.0:8000",
bind => "0.0.0.0:8642",

%% Protocol: wsgi or asgi
worker_class => wsgi,
Expand Down
12 changes: 6 additions & 6 deletions docs/guides/benchmarking.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,22 +222,22 @@ rebar3 shell

# In Erlang shell:
hornbeam:start("myapp:application", #{
bind => <<"127.0.0.1:8000">>,
bind => <<"127.0.0.1:8642">>,
worker_class => wsgi
}).

# In another terminal, run wrk:
wrk -t4 -c100 -d30s --latency http://127.0.0.1:8000/
wrk -t4 -c100 -d30s --latency http://127.0.0.1:8642/
```

### Using Apache Bench (ab)

```bash
# Simple benchmark
ab -n 10000 -c 100 -k http://127.0.0.1:8000/
ab -n 10000 -c 100 -k http://127.0.0.1:8642/

# High concurrency
ab -n 5000 -c 500 -k http://127.0.0.1:8000/
ab -n 5000 -c 500 -k http://127.0.0.1:8642/
```

### Key wrk Flags
Expand Down Expand Up @@ -323,8 +323,8 @@ The simple "Hello World" benchmarks measure raw server overhead. For realistic n
hornbeam:start("myapp:app", #{...}).

# Benchmark specific endpoints
wrk -t4 -c100 -d30s http://localhost:8000/api/users
wrk -t4 -c100 -d30s http://localhost:8000/api/search?q=test
wrk -t4 -c100 -d30s http://localhost:8642/api/users
wrk -t4 -c100 -d30s http://localhost:8642/api/search?q=test
```

Consider:
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/custom-apps.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ start() ->

%% Start the server
hornbeam:start("app:app", #{
bind => "0.0.0.0:8000",
bind => "0.0.0.0:8642",
worker_class => asgi,
pythonpath => ["priv/python"]
}).
Expand Down Expand Up @@ -388,7 +388,7 @@ handle(Req) ->
{cache_ttl, 3600}
]},
{hornbeam, [
{bind, "0.0.0.0:8000"},
{bind, "0.0.0.0:8642"},
{workers, 8},
{worker_class, asgi},
{timeout, 30000}
Expand Down
8 changes: 4 additions & 4 deletions docs/guides/erlang-apps.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ my_app/
hornbeam
]},
{env, [
{http_port, 8000},
{http_port, 8642},
{python_app, "app:application"},
{worker_class, wsgi}
]},
Expand Down Expand Up @@ -287,7 +287,7 @@ init_hooks() ->
%% config/sys.config
[
{my_app, [
{http_port, 8000},
{http_port, 8642},
{python_app, "app:application"},
{worker_class, asgi},
{api_key, "${API_KEY}"},
Expand Down Expand Up @@ -464,7 +464,7 @@ COPY --from=builder /app/_build/prod/rel/my_app /app
COPY priv/python/requirements.txt /tmp/
RUN pip install --no-cache-dir -r /tmp/requirements.txt
WORKDIR /app
EXPOSE 8000
EXPOSE 8642
CMD ["bin/my_app", "foreground"]
```

Expand Down Expand Up @@ -523,7 +523,7 @@ end_per_suite(_Config) ->

test_api(_Config) ->
Client = livery_client:new(#{}),
{ok, Resp} = livery_client:get(Client, <<"http://localhost:8000/">>),
{ok, Resp} = livery_client:get(Client, <<"http://localhost:8642/">>),
200 = livery_client:status(Resp),
{full, Body} = livery_client:body(Resp),
true = is_binary(Body),
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/multi-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ hornbeam:start(#{
worker_class => wsgi
}}
],
bind => "0.0.0.0:8000"
bind => "0.0.0.0:8642"
}).
```

Expand All @@ -135,7 +135,7 @@ hornbeam:start(#{
],

%% Global options
bind => "0.0.0.0:8000",
bind => "0.0.0.0:8642",
pythonpath => [".", "apps"],
venv => "/path/to/venv",
ssl => true,
Expand Down
4 changes: 2 additions & 2 deletions docs/guides/websocket.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ app = Starlette(routes=[
### Using websocat

```bash
websocat ws://localhost:8000/ws
websocat ws://localhost:8642/ws
```

### Using Python
Expand All @@ -358,7 +358,7 @@ import asyncio
import websockets

async def test():
async with websockets.connect('ws://localhost:8000/ws') as ws:
async with websockets.connect('ws://localhost:8642/ws') as ws:
await ws.send('Hello!')
response = await ws.recv()
print(response)
Expand Down
Loading
Loading