From 81ef9eb609bea1e8d97487aadadf4ad1b22325dc Mon Sep 17 00:00:00 2001 From: Junbo Wang Date: Fri, 14 Aug 2026 18:04:05 +0800 Subject: [PATCH] [gateway] Introduce the fluss-gateway module scaffolding --- .github/workflows/ci.yaml | 2 + .github/workflows/gateway-ci.yml | 127 ++++++++++++++++++++++++++++ .github/workflows/license-check.yml | 2 + fluss-gateway/.gitignore | 15 ++++ fluss-gateway/.licenserc.yaml | 37 ++++++++ fluss-gateway/Cargo.lock | 7 ++ fluss-gateway/Cargo.toml | 48 +++++++++++ fluss-gateway/README.md | 74 ++++++++++++++++ fluss-gateway/copyright.txt | 17 ++++ fluss-gateway/deny.toml | 36 ++++++++ fluss-gateway/justfile | 55 ++++++++++++ fluss-gateway/rust-toolchain.toml | 20 +++++ fluss-gateway/rustfmt.toml | 19 +++++ fluss-gateway/src/lib.rs | 33 ++++++++ fluss-gateway/src/main.rs | 29 +++++++ 15 files changed, 521 insertions(+) create mode 100644 .github/workflows/gateway-ci.yml create mode 100644 fluss-gateway/.gitignore create mode 100644 fluss-gateway/.licenserc.yaml create mode 100644 fluss-gateway/Cargo.lock create mode 100644 fluss-gateway/Cargo.toml create mode 100644 fluss-gateway/README.md create mode 100644 fluss-gateway/copyright.txt create mode 100644 fluss-gateway/deny.toml create mode 100644 fluss-gateway/justfile create mode 100644 fluss-gateway/rust-toolchain.toml create mode 100644 fluss-gateway/rustfmt.toml create mode 100644 fluss-gateway/src/lib.rs create mode 100644 fluss-gateway/src/main.rs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ee4a269d734..4cc35738866 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -26,12 +26,14 @@ on: - 'website/**' - 'helm/**' - 'fluss-rust/**' + - 'fluss-gateway/**' - '**/*.md' pull_request: paths-ignore: - 'website/**' - 'helm/**' - 'fluss-rust/**' + - 'fluss-gateway/**' - '**/*.md' concurrency: diff --git a/.github/workflows/gateway-ci.yml b/.github/workflows/gateway-ci.yml new file mode 100644 index 00000000000..f1a897e8019 --- /dev/null +++ b/.github/workflows/gateway-ci.yml @@ -0,0 +1,127 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# CI gates for the fluss-gateway module. The gateway is its own Cargo workspace, +# so it gets its own workflow: triggering on gateway changes never builds the +# fluss-rust workspace, and fluss-rust changes never build the gateway. `uses:` +# step inputs stay relative to the repository root. +name: Gateway CI + +on: + push: + branches: + - main + paths: + - 'fluss-gateway/**' + - '.github/workflows/gateway-ci.yml' + pull_request: + branches: + - main + paths: + - 'fluss-gateway/**' + - '.github/workflows/gateway-ci.yml' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: true + +defaults: + run: + working-directory: fluss-gateway + +jobs: + build-and-unit-test: + name: "Gateway Build and Tests" + timeout-minutes: 60 + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: + - ubuntu-latest + - macos-latest + steps: + - uses: actions/checkout@v6 + + - name: Rust Cache + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + with: + workspaces: fluss-gateway + + - name: Build + run: cargo build --all-targets + + - name: Unit Test + run: cargo test --all-targets + env: + RUST_LOG: DEBUG + RUST_BACKTRACE: full + + msrv: + name: "Gateway MSRV (1.88)" + # The rust-toolchain.toml floats to stable, so a plain build never catches use of features newer + # than the declared rust-version. Pin the MSRV explicitly here; `+toolchain` overrides the file. + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Install the MSRV toolchain + run: rustup toolchain install 1.88.0 --profile minimal + + - name: Rust Cache + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + with: + workspaces: fluss-gateway + + - name: Check on the declared MSRV + run: cargo +1.88.0 check --all-targets + + check-license-and-formatting: + name: "Gateway License and Formatting Check" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Check License Header + uses: apache/skywalking-eyes/header@61275cc80d0798a405cb070f7d3a8aaf7cf2c2c1 # v0.8.0 + with: + config: fluss-gateway/.licenserc.yaml + + - name: Install cargo-deny + uses: taiki-e/install-action@v2 + with: + tool: cargo-deny@0.14.22 + + - name: Check dependency licenses (Apache-compatible) + run: cargo deny check licenses + + - name: Rust Cache + uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + with: + workspaces: fluss-gateway + + - name: Format + run: cargo fmt --all -- --check + + - name: Clippy + run: cargo clippy --all-targets -- -D warnings + + - name: Rustdoc + run: cargo doc --no-deps + env: + RUSTDOCFLAGS: -D warnings diff --git a/.github/workflows/license-check.yml b/.github/workflows/license-check.yml index aa69703eec0..71f7fa70fc0 100644 --- a/.github/workflows/license-check.yml +++ b/.github/workflows/license-check.yml @@ -21,11 +21,13 @@ on: push: paths-ignore: - 'fluss-rust/**' + - 'fluss-gateway/**' - 'website/**' - '**/*.md' pull_request: paths-ignore: - 'fluss-rust/**' + - 'fluss-gateway/**' - 'website/**' - '**/*.md' diff --git a/fluss-gateway/.gitignore b/fluss-gateway/.gitignore new file mode 100644 index 00000000000..7731b5c1168 --- /dev/null +++ b/fluss-gateway/.gitignore @@ -0,0 +1,15 @@ +.DS_Store + +# Generated by Cargo +debug/ +target/ + +# Backup files generated by rustfmt +**/*.rs.bk + +# Debug information generated by MSVC builds of rustc +*.pdb + +# Editors +.idea/ +.vscode/ diff --git a/fluss-gateway/.licenserc.yaml b/fluss-gateway/.licenserc.yaml new file mode 100644 index 00000000000..df7a3ec353a --- /dev/null +++ b/fluss-gateway/.licenserc.yaml @@ -0,0 +1,37 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +header: + license: + spdx-id: Apache-2.0 + copyright-owner: Apache Software Foundation + + paths: + - 'fluss-gateway/**' + + paths-ignore: + # bare (gitignore-style) patterns match the basename at any depth + - '.gitignore' + - 'Cargo.lock' + - 'LICENSE' + - 'NOTICE' + - 'DISCLAIMER' + - '**/*.md' + - 'fluss-gateway/DEPENDENCIES.*.tsv' + # The checked-in OpenAPI document is generated from the typed contract (`just openapi`). + - 'fluss-gateway/openapi.yaml' + comment: on-failure diff --git a/fluss-gateway/Cargo.lock b/fluss-gateway/Cargo.lock new file mode 100644 index 00000000000..a8b82e7177a --- /dev/null +++ b/fluss-gateway/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "fluss-gateway" +version = "1.0.0" diff --git a/fluss-gateway/Cargo.toml b/fluss-gateway/Cargo.toml new file mode 100644 index 00000000000..40afecfa18b --- /dev/null +++ b/fluss-gateway/Cargo.toml @@ -0,0 +1,48 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +# The gateway is its own Cargo workspace and deliberately stays out of the +# workspace rooted at ../fluss-rust so that gateway dependencies never touch +# that workspace's lock file or its generated dependency inventories. +[workspace] +resolver = "3" + +[package] +name = "fluss-gateway" +edition = "2024" +version = "1.0.0" +license = "Apache-2.0" +# Keep in sync with the `gateway-msrv` CI job, which pins this exact toolchain. +rust-version = "1.88" +authors = ["Apache Fluss "] +repository = "https://github.com/apache/fluss" +# The gateway ships as an executable, not a library on crates.io. +publish = false +description = "Stateless REST gateway for Apache Fluss" + +[[bin]] +name = "fluss-gateway" +path = "src/main.rs" + +# Internal testability boundary for the executable; this is not a published or supported Rust SDK. +[lib] +name = "fluss_gateway" + +# This change only introduces the module scaffolding: manifest, toolchain, lint +# and license configuration, and placeholder targets, with no dependencies. +# The runtime (configuration, lifecycle, HTTP layer, and tests) arrives with +# the Gateway foundation change (FIP-49) and brings its dependencies with it. diff --git a/fluss-gateway/README.md b/fluss-gateway/README.md new file mode 100644 index 00000000000..3c5c09723d9 --- /dev/null +++ b/fluss-gateway/README.md @@ -0,0 +1,74 @@ + + +# Apache Fluss Gateway + +A stateless REST gateway for Apache Fluss. It exposes REST APIs for writing to +Fluss tables and performing DDL operations, while keeping no session, cursor, +or replay state: any instance can serve any request behind a plain load +balancer. + +The gateway is an executable, not a library on crates.io, and it is its own +Cargo workspace so its dependencies never touch the `fluss-rust` workspace's +lock file or its generated dependency inventories. + +## Status + +This module currently contains only the scaffolding: the manifest with +placeholder bin/lib targets, the pinned toolchain, lint and license +configuration, and the developer recipes. The runtime — configuration, +lifecycle management, the REST layer, and the test suites — lands in follow-up +pull requests. + +## Prerequisites + +- Rust toolchain managed by [rustup](https://rustup.rs); the workspace pins the + channel in `rust-toolchain.toml` (stable with `rustfmt` and `clippy`) +- The declared minimum supported Rust version is 1.88, enforced by the + `gateway-msrv` CI job +- [`just`](https://github.com/casey/just) for the recipes below + +## Build and test + +Run everything from this directory, or use the `just` recipes: + +```bash +just build # cargo build --all-targets +just test # cargo test --all-targets +just fmt-check # cargo fmt --all -- --check +just clippy # cargo clippy --all-targets -- -D warnings +just doc # RUSTDOCFLAGS="-D warnings" cargo doc --no-deps +just licenses # cargo deny check licenses +``` + +The MSRV can be verified locally with `cargo +1.88.0 check --all-targets`. + +## CI + +Gateway changes are gated by a dedicated workflow, `.github/workflows/gateway-ci.yml` +(build and tests on Linux/macOS, MSRV 1.88, license headers, dependency +licenses via `cargo-deny`, formatting, clippy, rustdoc). Gateway-only changes +are excluded from the Java CI, mirroring `fluss-rust`, and the gateway workflow +never builds the `fluss-rust` workspace. + +## License enforcement + +Like `fluss-rust`, the gateway carries its own license enforcement: source +headers are checked by `skywalking-eyes` (`.licenserc.yaml`) and dependency +licenses by `cargo-deny` (`deny.toml`). Both run in CI. diff --git a/fluss-gateway/copyright.txt b/fluss-gateway/copyright.txt new file mode 100644 index 00000000000..d5519133edc --- /dev/null +++ b/fluss-gateway/copyright.txt @@ -0,0 +1,17 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/fluss-gateway/deny.toml b/fluss-gateway/deny.toml new file mode 100644 index 00000000000..18ed544033f --- /dev/null +++ b/fluss-gateway/deny.toml @@ -0,0 +1,36 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[licenses] +allow = [ + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-2-Clause", + "BSD-3-Clause", + "CC0-1.0", + "ISC", + "MIT", + "Unicode-3.0", + "Zlib", +] + +exceptions = [ + # open data licenses that SHOULD be OK + { crate = "webpki-roots", allow = [ + "CDLA-Permissive-2.0", + ] }, +] \ No newline at end of file diff --git a/fluss-gateway/justfile b/fluss-gateway/justfile new file mode 100644 index 00000000000..bbeb59088f2 --- /dev/null +++ b/fluss-gateway/justfile @@ -0,0 +1,55 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +# Recipes for the fluss-gateway module. The module is its own Cargo workspace, +# so every recipe runs cargo from this directory. + +# Build the gateway and every test target in debug mode. +build: + cargo build --all-targets + +# Build the gateway with the release profile. +build-release: + cargo build --release + +# Run all tests of the gateway. +test: + cargo test --all-targets + +# Format the gateway sources in place. +fmt: + cargo fmt --all + +# Verify formatting without changing any file. +fmt-check: + cargo fmt --all -- --check + +# Lint the gateway with clippy, treating warnings as errors. +clippy: + cargo clippy --all-targets -- -D warnings + +# Build the API documentation for this package only. +doc: + RUSTDOCFLAGS="-D warnings" cargo doc --no-deps + +# Run the gateway binary, forwarding any flags, e.g. just run --version +run *flags: + cargo run -- {{flags}} + +# Check that every dependency license is compatible with the Apache License. +licenses: + cargo deny check licenses diff --git a/fluss-gateway/rust-toolchain.toml b/fluss-gateway/rust-toolchain.toml new file mode 100644 index 00000000000..870d7eb7afc --- /dev/null +++ b/fluss-gateway/rust-toolchain.toml @@ -0,0 +1,20 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +[toolchain] +channel = "stable" +components = ["rustfmt", "clippy"] diff --git a/fluss-gateway/rustfmt.toml b/fluss-gateway/rustfmt.toml new file mode 100644 index 00000000000..18d114826f6 --- /dev/null +++ b/fluss-gateway/rustfmt.toml @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +edition = "2024" +reorder_imports = true \ No newline at end of file diff --git a/fluss-gateway/src/lib.rs b/fluss-gateway/src/lib.rs new file mode 100644 index 00000000000..b0fff82dbba --- /dev/null +++ b/fluss-gateway/src/lib.rs @@ -0,0 +1,33 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Internal implementation crate of the Fluss Gateway. +//! +//! The gateway is a stateless REST front end for Apache Fluss (FIP-49): it +//! keeps no session, cursor, or replay state, so any instance can serve any +//! request behind a plain load balancer. This change only reserves the crate +//! layout; the runtime modules arrive with the Gateway foundation change. + +#[cfg(test)] +mod tests { + // A single smoke test so the CI build-and-test gate proves the test + // harness is wired up from day one; real suites arrive with the runtime. + #[test] + fn crate_layout_is_wired() { + assert_eq!(env!("CARGO_PKG_NAME"), "fluss-gateway"); + } +} diff --git a/fluss-gateway/src/main.rs b/fluss-gateway/src/main.rs new file mode 100644 index 00000000000..066e7302fbb --- /dev/null +++ b/fluss-gateway/src/main.rs @@ -0,0 +1,29 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +//! Placeholder entry point of the Fluss Gateway executable. +//! +//! This change only reserves the crate layout. The runtime — configuration, +//! lifecycle management, and the REST layer — arrives with the Gateway +//! foundation change described by FIP-49. + +fn main() { + println!( + "fluss-gateway {} (scaffolding only, the runtime is not wired yet)", + env!("CARGO_PKG_VERSION") + ); +}