Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .claude/rules/code-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Code Coverage Measurement

- Use `make coverage` to measure code coverage. This is the authoritative source.
9 changes: 9 additions & 0 deletions .claude/rules/github-actions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
paths:
- ".github/actions/**/*"
---

# GitHub Actions Standards

- Actions must represent a single purpose and a single concern.
- Compose actions if they need to provide a more complex functionality.
7 changes: 5 additions & 2 deletions .claude/rules/github-workflows.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
---
paths:
- ".github/**/*"
- ".github/workflows/**/*"
---

# GitHub Workflows Standards

- Always use Makefile targets in the workflow to avoid code duplication.
- Always use Makefile targets in the workflow to avoid code duplication (if they need to run something that is already present in a Makefile).
- Never add the tests that use LLMs to GitHub workflows, because the default GitHub worker does not have the capacity to run them.
- Only add unit tests to GitHub workflows.
- Keep GitHub workflows responsible for only a single concern. For example, run linter, and tests in parallel.
- Treat GitHub workflows as a coding project. Use composable actions, factor similar concerns into actions.
- Encapsulate functionalities in composable actions.
- Keep the workflows clean and purposeful.
54 changes: 54 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = ["paddler", "paddler_bootstrap", "paddler_cli", "paddler_client", "paddler_client_cli", "paddler_gui", "paddler_tests", "paddler_types"]
members = ["paddler", "paddler_bootstrap", "paddler_cli", "paddler_client", "paddler_client_cli", "paddler_gui", "paddler_gui_tests", "paddler_ports", "paddler_tests", "paddler_types"]
resolver = "2"

[workspace.package]
Expand Down Expand Up @@ -58,6 +58,7 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
shellexpand = "3"
iced = { version = "0.14", features = ["image", "svg", "tokio"] }
iced_test = "=0.14.0"
if-addrs = "0.13"
statum = "0.6"
tempfile = "3.20.0"
Expand All @@ -71,6 +72,8 @@ url = { version = "2.5", features = ["serde"] }
paddler = { version = "4.0.0", path = "paddler" }
paddler_bootstrap = { version = "4.0.0", path = "paddler_bootstrap" }
paddler_client = { version = "4.0.0", path = "paddler_client" }
paddler_gui = { version = "4.0.0", path = "paddler_gui" }
paddler_ports = { version = "4.0.0", path = "paddler_ports" }
paddler_tests = { version = "4.0.0", path = "paddler_tests" }
paddler_types = { version = "4.0.0", path = "paddler_types" }

Expand Down
56 changes: 47 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.DEFAULT_GOAL := target/release/paddler

COVERAGE_PACKAGES := -p paddler_gui -p paddler_gui_tests
RUST_LOG ?= debug

PADDLER_CLI_SOURCES := $(shell find paddler/src paddler_bootstrap/src paddler_cli/src paddler_client/src paddler_types/src -name '*.rs')
Expand All @@ -20,30 +21,45 @@ node_modules: package-lock.json
esbuild-meta.json: $(FRONTEND_SOURCES) jarmuz-static.mjs tsconfig.json package.json node_modules
./jarmuz-static.mjs

target/debug/paddler: $(PADDLER_CLI_SOURCES)
cargo build -p paddler_cli

target/release/paddler: $(PADDLER_CLI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_cli --features web_admin_panel

target/cuda/debug/paddler: $(PADDLER_CLI_SOURCES) esbuild-meta.json
cargo build -p paddler_cli --features cuda,web_admin_panel --target-dir target/cuda

target/cuda/debug/paddler_gui: $(PADDLER_GUI_SOURCES) esbuild-meta.json
cargo build -p paddler_gui --features cuda,web_admin_panel --target-dir target/cuda

target/cuda/release/paddler: $(PADDLER_CLI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_cli --features cuda,web_admin_panel --target-dir target/cuda

target/cuda/release/paddler_gui: $(PADDLER_GUI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_gui --features cuda,web_admin_panel --target-dir target/cuda

target/debug/paddler: $(PADDLER_CLI_SOURCES)
cargo build -p paddler_cli

target/debug/paddler_gui: $(PADDLER_GUI_SOURCES) esbuild-meta.json
cargo build -p paddler_gui --features web_admin_panel

target/metal/debug/paddler: $(PADDLER_CLI_SOURCES) esbuild-meta.json
cargo build -p paddler_cli --features metal,web_admin_panel --target-dir target/metal

target/metal/debug/paddler_gui: $(PADDLER_GUI_SOURCES) esbuild-meta.json
cargo build -p paddler_gui --features metal,web_admin_panel --target-dir target/metal

target/metal/release/paddler: $(PADDLER_CLI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_cli --features metal,web_admin_panel --target-dir target/metal

target/vulkan/release/paddler: $(PADDLER_CLI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_cli --features vulkan,web_admin_panel --target-dir target/vulkan
target/metal/release/paddler_gui: $(PADDLER_GUI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_gui --features metal,web_admin_panel --target-dir target/metal

target/release/paddler: $(PADDLER_CLI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_cli --features web_admin_panel

target/release/paddler_gui: $(PADDLER_GUI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_gui --features web_admin_panel

target/vulkan/release/paddler: $(PADDLER_CLI_SOURCES) esbuild-meta.json
cargo build --release -p paddler_cli --features vulkan,web_admin_panel --target-dir target/vulkan

# -----------------------------------------------------------------------------
# Phony targets
# -----------------------------------------------------------------------------
Expand All @@ -59,6 +75,28 @@ clean:
clippy: esbuild-meta.json
cargo clippy --workspace --all-targets --features web_admin_panel,tests_that_use_llms,tests_that_use_compiled_paddler

.PHONY: coverage
coverage: esbuild-meta.json
cargo llvm-cov clean --workspace
cargo llvm-cov $(COVERAGE_PACKAGES) --features web_admin_panel --no-report
cargo llvm-cov report --json --output-path target/llvm-cov.json
cargo llvm-cov report --lcov --output-path target/lcov.info
cargo llvm-cov report
npx rust-coverage-check target/llvm-cov.json \
--workspace-root $(CURDIR) \
--gated paddler_gui \
--required-percent 100

.PHONY: coverage-clean
coverage-clean:
cargo llvm-cov clean --workspace
rm -rf target/llvm-cov-target
rm -f target/llvm-cov.json target/lcov.info

.PHONY: coverage-report
coverage-report: esbuild-meta.json
cargo llvm-cov $(COVERAGE_PACKAGES) --features web_admin_panel --html

.PHONY: fmt
fmt: node_modules
./jarmuz-fmt.mjs
Expand All @@ -80,7 +118,7 @@ test.integration.metal: target/metal/debug/paddler

.PHONY: test.unit
test.unit: esbuild-meta.json
cargo test --features web_admin_panel
cargo test --workspace --features web_admin_panel

.PHONY: build.client.js
build.client.js:
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"devDependencies": {
"@intentee/rust-coverage-check": "0.1.0",
"@types/hotwired__turbo": "^8",
"@types/react": "^19.1.10",
"@types/react-dom": "^19.1.7",
Expand Down
23 changes: 16 additions & 7 deletions paddler/src/balancer/compatibility/openai_service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod app_data;
pub mod configuration;
pub mod http_route;

use std::net::TcpListener;
use std::sync::Arc;

use actix_web::App;
Expand All @@ -22,6 +23,7 @@ use crate::service::Service;
pub struct OpenAIService {
pub buffered_request_manager: Arc<BufferedRequestManager>,
pub inference_service_configuration: InferenceServiceConfiguration,
pub listener: Option<TcpListener>,
pub openai_service_configuration: OpenAIServiceConfiguration,
}

Expand All @@ -43,8 +45,10 @@ impl Service for OpenAIService {
inference_service_configuration: self.inference_service_configuration.clone(),
});

#[expect(clippy::expect_used, reason = "server bind failure is unrecoverable")]
HttpServer::new(move || {
let taken_listener = self.listener.take();
let configured_addr = self.openai_service_configuration.addr;

let bound = HttpServer::new(move || {
App::new()
.wrap(create_cors_middleware(&cors_allowed_hosts_arc))
.app_data(app_data.clone())
Expand All @@ -54,11 +58,16 @@ impl Service for OpenAIService {
.shutdown_signal(async move {
shutdown.cancelled().await;
})
.disable_signals()
.bind(self.openai_service_configuration.addr)
.expect("Unable to bind server to address")
.run()
.await?;
.disable_signals();

#[expect(clippy::expect_used, reason = "server bind failure is unrecoverable")]
let bound = match taken_listener {
Some(listener) => bound.listen(listener),
None => bound.bind(configured_addr),
}
.expect("Unable to bind/listen server on address");

bound.run().await?;

Ok(())
}
Expand Down
23 changes: 16 additions & 7 deletions paddler/src/balancer/inference_service/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod app_data;
pub mod configuration;
pub mod http_route;

use std::net::TcpListener;
use std::sync::Arc;

use actix_web::App;
Expand All @@ -27,6 +28,7 @@ pub struct InferenceService {
pub balancer_applicable_state_holder: Arc<BalancerApplicableStateHolder>,
pub buffered_request_manager: Arc<BufferedRequestManager>,
pub configuration: InferenceServiceConfiguration,
pub listener: Option<TcpListener>,
#[cfg(feature = "web_admin_panel")]
pub web_admin_panel_service_configuration: Option<WebAdminPanelServiceConfiguration>,
}
Expand Down Expand Up @@ -56,8 +58,10 @@ impl Service for InferenceService {
shutdown: shutdown.clone(),
});

#[expect(clippy::expect_used, reason = "server bind failure is unrecoverable")]
HttpServer::new(move || {
let taken_listener = self.listener.take();
let configured_addr = self.configuration.addr;

let bound = HttpServer::new(move || {
App::new()
.wrap(create_cors_middleware(&cors_allowed_hosts_arc))
.app_data(app_data.clone())
Expand All @@ -70,11 +74,16 @@ impl Service for InferenceService {
.shutdown_signal(async move {
shutdown.cancelled().await;
})
.disable_signals()
.bind(self.configuration.addr)
.expect("Unable to bind server to address")
.run()
.await?;
.disable_signals();

#[expect(clippy::expect_used, reason = "server bind failure is unrecoverable")]
let bound = match taken_listener {
Some(listener) => bound.listen(listener),
None => bound.bind(configured_addr),
}
.expect("Unable to bind/listen server on address");

bound.run().await?;

Ok(())
}
Expand Down
Loading
Loading