Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
2f51c16
refactor(consul)!: adopt typed plugin construction
nick2781 Oct 26, 2026
fc9035a
fix(hash)!: standardize Murmur digests and retain legacy MSVC access
nick2781 Oct 26, 2026
d8b3a61
test(hash): isolate standalone Murmur header checks
nick2781 Oct 26, 2026
b794cfc
test(consul): exercise construction across application jobs
nick2781 Oct 26, 2026
87e24d4
docs(hash): distinguish affected routing consumers
nick2781 Oct 26, 2026
c9bdebe
chore(consul): synchronize preceding merge candidate
nick2781 Oct 26, 2026
5a8b002
chore(hash): synchronize preceding merge candidate
nick2781 Oct 26, 2026
15b0901
docs(consul): publish construction guide in canonical pages
nick2781 Oct 26, 2026
7f2256f
build(deps): bump fast-uri from 3.1.8 to 3.1.9 in /docs/site
dependabot[bot] Oct 26, 2026
3bed670
refactor(proto): remove unused codec scaffolding
nick2781 Oct 26, 2026
53222f8
refactor(hash): remove platform header dependencies
nick2781 Oct 26, 2026
5a4944c
chore(integration): synchronize accepted hash candidate
nick2781 Oct 26, 2026
69af843
chore(hash): synchronize preceding Consul candidate
nick2781 Oct 26, 2026
ab53c06
chore(integration): synchronize preceding plugin changes
nick2781 Oct 26, 2026
9c6b94e
chore(integration): synchronize preceding header cleanup
nick2781 Oct 26, 2026
94009f4
build(deps): combine fast-uri update with Consul validation
nick2781 Oct 26, 2026
40795f8
chore(integration): synchronize preceding merge candidate
nick2781 Oct 26, 2026
2f6cdf4
refactor(etcd)!: replace plugin creation macros
nick2781 Oct 26, 2026
ae9b546
chore(integration): combine preceding cleanup with Etcd construction
nick2781 Oct 26, 2026
d38982c
fix(tests): probe Net DSO listener and peer closure
nick2781 Oct 26, 2026
5c621eb
fix(tests): bound the Net listener shutdown probe
nick2781 Oct 26, 2026
dd02b81
chore(integration): retain the Net listener test fix
nick2781 Oct 26, 2026
37a88f3
chore(integration): include the Net listener test fix
nick2781 Oct 26, 2026
7bba7de
chore(integration): synchronize preceding merge candidate
nick2781 Oct 26, 2026
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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ jobs:
-DARK_BUILD_BENCHMARKS=ON
-DARK_BUILD_PLUGIN_HTTP=ON
-DARK_BUILD_PLUGIN_CONSUL=ON
-DARK_BUILD_PLUGIN_ETCD_CLIENT=ON
-DARK_BUILD_PROTO=ON
-DARK_BUILD_TESTS=ON
-DARK_BUILD_CORE_TESTS=ON
Expand Down
2 changes: 2 additions & 0 deletions docs/guides/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,5 @@ Net constructs its HTTP client through a private factory returning `std::unique_
Kernel also uses typed construction while retaining its public `*_impl` and `kernel_plugin` types and header paths. Its private factory header is not installed. Rebuild Kernel and consumers together because those public class layouts change; the [Kernel migration table](../reference/kernel.md#typed-kernel-construction) records unchanged interface keys, update selection and registration order.

Consul follows the same construction pattern while retaining all three public headers and types. Its private factory is not installed; the module keeps its interface RTTI key and disabled updates. Rebuild Consul and consumers together because its public implementation/plugin layouts change. See [Consul construction migration](../reference/directory-structure.md#typed-consul-construction) for test entry points and dependency conditions.

Etcd Client also retains all five public headers and types while using typed bases, a private interface-returning factory and explicit entry/exit functions. Its interface RTTI key and disabled updates are unchanged. Rebuild the plugin and consumers together because the public implementation/plugin layouts change. The [Etcd Client construction migration](../reference/directory-structure.md#typed-etcd-client-construction) describes optional JSON dependencies and tests without an Etcd service.
2 changes: 2 additions & 0 deletions docs/guides/plugins_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,3 +200,5 @@ Net 通过私有工厂返回 `std::unique_ptr<http_client_module>`,并启用
Kernel 同样使用类型化构造,并保留公开 `*_impl`、`kernel_plugin` 类型与头路径;私有工厂头不安装。公开类布局发生变化,Kernel 与消费者需要一起重建。[Kernel 迁移表](../reference/kernel_CN.md#kernel-类型化构造)记录保持不变的接口键、update 选择与注册顺序。

Consul 使用相同构造方式,保留全部三个公开头与类型。私有工厂不安装;模块保留接口 RTTI 键和禁用 update 的选择。公开实现/插件布局发生变化,Consul 与消费者必须一起重建。测试入口与依赖条件见 [Consul 构造迁移](../reference/directory-structure_CN.md#consul-类型化构造)。

Etcd Client 使用类型化基类、返回接口的私有工厂与显式入口/出口,保留全部五个公开头与类型。接口 RTTI 键和禁用 update 的选择不变。公开实现/插件布局发生变化,插件与消费者必须一起重建。可选 JSON 依赖与无需 Etcd 服务的测试见 [Etcd Client 构造迁移](../reference/directory-structure_CN.md#etcd-client-类型化构造)。
4 changes: 2 additions & 2 deletions docs/reference/build-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ cmake -S . -B build -DARK_BUILD_APPLICATIONS=ON \
cmake --build build --target ark_mysql_plugin ark_redis_plugin
```

All official plugin public headers are copied from explicit lists at configuration time into each build tree's generated plugin header mapping. Each `ark::<name>` API target carries that include root even with runtime plugins disabled. MySQL, Redis, Utility, Net, Bus and HTTP exclude private assembly and factories. Kernel retains all 38 existing headers, including `kernel_plugin.hpp`; Consul, Etcd Client, Kafka, OSS SDK and Physic retain all 22 existing public headers, including implementation and assembly headers. Registration keys, public type visibility and optional plugin policies are retained; [Kernel typed construction](kernel.md#typed-kernel-construction) and [Consul typed construction](directory-structure.md#typed-consul-construction) change public class layouts and require rebuilding consumers. Their private factory headers are excluded from mapping and installation; header mapping does not validate optional driver integrations. Each public header has one co-located source; its generated include mapping belongs to the selected build tree, rather than a second source layout.
All official plugin public headers are copied from explicit lists at configuration time into each build tree's generated plugin header mapping. Each `ark::<name>` API target carries that include root even with runtime plugins disabled. MySQL, Redis, Utility, Net, Bus and HTTP exclude private assembly and factories. Kernel retains all 38 existing headers, including `kernel_plugin.hpp`; Consul, Etcd Client, Kafka, OSS SDK and Physic retain all 22 existing public headers, including implementation and assembly headers. Registration keys, public type visibility and optional plugin policies are retained; [Kernel typed construction](kernel.md#typed-kernel-construction), [Consul typed construction](directory-structure.md#typed-consul-construction) and [Etcd Client typed construction](directory-structure.md#typed-etcd-client-construction) change public class layouts and require rebuilding consumers. Their private factory headers are excluded from mapping and installation; header mapping does not validate optional driver integrations. Each public header has one co-located source; its generated include mapping belongs to the selected build tree, rather than a second source layout.

Applications CI enables the optional Consul plugin on Linux, macOS and Windows. Its `check-core` run includes construction, DLL lifecycle and production export checks; these checks require no Consul service and do not establish service interoperability.
Applications CI explicitly enables Consul and Etcd Client on Linux, macOS and Windows. Its `check-core` run includes their construction, DLL lifecycle and production export checks; these checks require no Consul or Etcd service and do not establish service interoperability. Etcd Client keeps its existing default `ON` selection and can be disabled with `ARK_BUILD_PLUGIN_ETCD_CLIENT=OFF`. Building it requires the existing `nlohmann_json` package (`etcd-client` vcpkg feature); disabling it does not add that JSON dependency to core tests.

Link a consumer to `ark::mysql` and/or `ark::redis` for the public headers and usage requirements. These public interface targets do not load a runtime library. Deploy the selected libraries with the launcher and add their stems to the application's manifest:

Expand Down
4 changes: 2 additions & 2 deletions docs/reference/build-options_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ cmake -S . -B build -DARK_BUILD_APPLICATIONS=ON \
cmake --build build --target ark_mysql_plugin ark_redis_plugin
```

全部官方插件的公开头通过显式清单在配置阶段复制到各构建树生成的插件公开头映射。各 `ark::<name>` API target 传递该目录,插件关闭时仍可使用。MySQL、Redis、Utility、Net、Bus、HTTP 的私有装配头和工厂不进入映射;Kernel 保留包括 `kernel_plugin.hpp` 在内的原有 38 个头;Consul、Etcd Client、Kafka、OSS SDK、Physic 保留包括实现头与装配头在内的原有 22 个公开头。注册键、公开类型可见性和可选插件策略继续保留;[Kernel 类型化构造](kernel_CN.md#kernel-类型化构造)与 [Consul 类型化构造](directory-structure_CN.md#consul-类型化构造)改变公开类布局,需要重建消费者。两者的私有工厂头均不映射、不安装;头文件映射不代表可选驱动集成已经验证。每个公共头仅有一份共置源码;生成的头文件映射属于选定构建树,不构成第二棵源码目录。
全部官方插件的公开头通过显式清单在配置阶段复制到各构建树生成的插件公开头映射。各 `ark::<name>` API target 传递该目录,插件关闭时仍可使用。MySQL、Redis、Utility、Net、Bus、HTTP 的私有装配头和工厂不进入映射;Kernel 保留包括 `kernel_plugin.hpp` 在内的原有 38 个头;Consul、Etcd Client、Kafka、OSS SDK、Physic 保留包括实现头与装配头在内的原有 22 个公开头。注册键、公开类型可见性和可选插件策略继续保留;[Kernel 类型化构造](kernel_CN.md#kernel-类型化构造)、[Consul 类型化构造](directory-structure_CN.md#consul-类型化构造)与 [Etcd Client 类型化构造](directory-structure_CN.md#etcd-client-类型化构造)改变公开类布局,需要重建消费者。这些私有工厂头均不映射、不安装;头文件映射不代表可选驱动集成已经验证。每个公共头仅有一份共置源码;生成的头文件映射属于选定构建树,不构成第二棵源码目录。

应用 CI 在 Linux、macOS、Windows 启用可选 Consul 插件,`check-core` 包含构造、动态库生命周期与生产库导出检查。这些检查不需要 Consul 服务,也不代表服务互通验收。
应用 CI 在 Linux、macOS、Windows 显式启用 Consul 与 Etcd Client,`check-core` 包含两者的构造、动态库生命周期与生产库导出检查。这些检查不需要 Consul 或 Etcd 服务,也不代表服务互通验收。Etcd Client 保留现有默认 `ON` 选择,可通过 `ARK_BUILD_PLUGIN_ETCD_CLIENT=OFF` 关闭。构建它需要现有 `nlohmann_json` 软件包(vcpkg 的 `etcd-client` feature);关闭它不会向核心测试增加该 JSON 依赖。

业务插件链接 `ark::mysql` 和/或 `ark::redis`,以获取公开头文件和编译要求;公共接口目标不会加载运行时动态库。将所需动态库与启动器一起部署,并在应用清单中填写库名称:

Expand Down
16 changes: 16 additions & 0 deletions docs/reference/directory-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,3 +180,19 @@ cmake --build build --target check-consul-construction --parallel 2
```

`ARK_BUILD_PLUGIN_CONSUL=ON` also requires `ARK_BUILD_APPLICATIONS=ON` and remains off by default. It links the generated protocol target `ark::proto` directly. With the core tests enabled, `check-consul-plugin` additionally inspects the actual Consul DSO exports in a separate process; `check-core` includes the applicable Consul checks. The controlled factory does not exercise the production HTTP client or a Consul server. These construction checks do not establish live Consul interoperability, protocol acceptance or arbitrary hot-update safety.

## Typed Etcd Client construction

**Breaking ABI/layout change:** `etcd_client_module_impl` now inherits `module_base<etcd_client_module>` and `etcd_client_plugin` inherits `plugin_base<etcd_client_plugin>`. Rebuild Etcd Client and consumers together. All five public headers, their `<ark/etcd_client/...>` paths and public types remain available through `ark::etcd_client`; the `etcd_client_module` and `etcd_client` interfaces are unchanged. C++ plugin boundaries do not promise compiler-independent ABI compatibility.

The private `etcd_client_factory.hpp` returns `std::unique_ptr<etcd_client_module>` and is excluded from public mappings and installation. Explicit `DllEntryPlugin` / `DllExitPlugin` retain the existing platform exports and logger setup. Registration uses the original interface RTTI key and `module_update::disabled`; unregistration destroys the owned module. HTTP-client lookup, endpoint handling, timeout argument order, lease requests and callbacks are unchanged. The existing `keepalive` stub remains incomplete; this construction change adds no protocol or Registry capability.

Etcd Client remains selected by default for application builds, with `ARK_BUILD_PLUGIN_ETCD_CLIENT=OFF` available to disable it. Its existing `nlohmann_json` package is required only when building the plugin (`etcd-client` vcpkg feature). With `ARK_BUILD_APPLICATIONS=ON`, `ARK_BUILD_PLUGIN_ETCD_CLIENT=ON`, `ARK_BUILD_PROTO=ON` and `ARK_BUILD_CORE_TESTS=ON`, run:

```sh
cmake --build build --target check-etcd-client-plugin --parallel 1
```

This target includes `check-etcd-client-construction`: actual factory/assembly doctest cases, plus a controlled-factory DSO using the production entry/exit source to check configuration handoff, interface metadata, disabled updates, exactly-once ownership and repeated stop. A separate process loads the actual production plugin, checks its entry/exit exports and unloads it. `check-core` includes both checks when the runtime plugin is selected; disabled-plugin core builds do not acquire the JSON dependency. Applications CI explicitly enables the plugin and runs these checks through its existing `check-core` job.

These tests do not run an Etcd service or exercise production HTTP/Etcd interoperability. They establish construction and DSO boundaries, not a completed Registry or arbitrary hot-update safety.
16 changes: 16 additions & 0 deletions docs/reference/directory-structure_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,3 +170,19 @@ cmake --build build --target check-consul-construction --parallel 2
```

`ARK_BUILD_PLUGIN_CONSUL=ON` 还要求 `ARK_BUILD_APPLICATIONS=ON`,默认保持关闭。插件直接链接生成协议目标 `ark::proto`。开启核心测试后,`check-consul-plugin` 还在独立进程中检查真实 Consul DSO 的导出符号;`check-core` 包含当前条件下可用的 Consul 检查。受控工厂不执行生产 HTTP 客户端或访问 Consul 服务。这些构造检查不代表真实 Consul 互通、协议验收或任意热更新安全。

## Etcd Client 类型化构造

**ABI/布局不兼容变更:** `etcd_client_module_impl` 现在继承 `module_base<etcd_client_module>`,`etcd_client_plugin` 继承 `plugin_base<etcd_client_plugin>`。Etcd Client 与消费者必须一起重建。全部五个公开头、`<ark/etcd_client/...>` 路径和公开类型继续通过 `ark::etcd_client` 提供,`etcd_client_module` 与 `etcd_client` 接口不变。C++ 插件边界不承诺跨编译器的 ABI 兼容性。

私有 `etcd_client_factory.hpp` 返回 `std::unique_ptr<etcd_client_module>`,不映射、不安装。显式 `DllEntryPlugin`/`DllExitPlugin` 保留原有平台导出和日志初始化。注册沿用原接口 RTTI 键,显式使用 `module_update::disabled`;注销时销毁拥有的模块。HTTP 客户端查找、端点处理、超时参数顺序、租约请求与回调保持不变。原有 `keepalive` 空实现仍未完成,本次构造调整不增加协议或 Registry 能力。

Etcd Client 保留应用构建默认选中的策略,可通过 `ARK_BUILD_PLUGIN_ETCD_CLIENT=OFF` 关闭。仅构建该插件时需要现有 `nlohmann_json` 软件包(vcpkg 的 `etcd-client` feature)。开启 `ARK_BUILD_APPLICATIONS=ON`、`ARK_BUILD_PLUGIN_ETCD_CLIENT=ON`、`ARK_BUILD_PROTO=ON` 与 `ARK_BUILD_CORE_TESTS=ON` 后,运行:

```sh
cmake --build build --target check-etcd-client-plugin --parallel 1
```

该目标包含 `check-etcd-client-construction`:真实工厂/装配的 doctest 用例,以及使用生产入口/出口源码与受控工厂的 DSO 测试,覆盖配置传递、接口元数据、禁用 update、所有权恰好销毁一次和重复 stop。另一个独立进程加载真实生产插件,检查入口/出口导出后卸载。选中运行时插件时,`check-core` 包含这两项检查;关闭插件的核心构建不增加 JSON 依赖。应用 CI 显式启用该插件,通过现有 `check-core` 任务执行检查。

这些测试不启动 Etcd 服务,不执行生产 HTTP/Etcd 互通验收,只验证构造与 DSO 边界,不代表 Registry 已完成,也不证明任意热更新安全。
13 changes: 13 additions & 0 deletions src/plugins/etcd_client/etcd_client_factory.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) 2026 OpenArkStudio. Licensed under Apache-2.0. See LICENSE.
#pragma once

#include <memory>

#include "ark/etcd_client/etcd_client_module.hpp"

// Plugin-private construction; deliberately absent from public header mappings.
namespace ark::detail {

std::unique_ptr<etcd_client_module> make_etcd_client_module();

} // namespace ark::detail
5 changes: 5 additions & 0 deletions src/plugins/etcd_client/etcd_client_module_impl.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
#include "ark/etcd_client/etcd_client_impl.hpp"
#include "ark/etcd_client/etcd_client_module_impl.hpp"
#include "etcd_client_factory.hpp"

namespace ark {

std::unique_ptr<etcd_client_module> detail::make_etcd_client_module() {
return std::make_unique<etcd_client_module_impl>();
}

bool etcd_client_module_impl::init() {
http_client_module_ = find_module<http_client_module>();
return http_client_module_ != nullptr;
Expand Down
10 changes: 4 additions & 6 deletions src/plugins/etcd_client/etcd_client_module_impl.hpp
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
#pragma once

#include "ark/etcd_client/etcd_client_module.hpp"
#include "ark/module_base.hpp"
#include "ark/net/http_client_module.hpp"
#include "ark/plugin_manager.hpp"

namespace ark {

class etcd_client_module_impl final : public etcd_client_module
class etcd_client_module_impl final : public module_base<etcd_client_module>
{
ARK_DECLARE_MODULE_FUNCTIONS

public:
virtual bool init() override;
bool init() override;

virtual std::shared_ptr<etcd_client> create_etcd_client(
std::shared_ptr<etcd_client> create_etcd_client(
std::vector<std::string> endpoints, int io_timeout = 5, int connect_timeout = 2) override;

private:
Expand Down
23 changes: 19 additions & 4 deletions src/plugins/etcd_client/etcd_client_plugin.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
#include "ark/etcd_client/etcd_client_module_impl.hpp"
#include <stdexcept>

#include "ark/etcd_client/etcd_client_plugin.hpp"
#include "etcd_client_factory.hpp"

namespace ark {

ARK_DECLARE_PLUGIN_DLL_FUNCTION(etcd_client_plugin)
ARK_EXPORT_FUNC void DllEntryPlugin(plugin_manager* manager, const std::string& name, logger* log) {
logger::init(log);
manager->register_plugin<etcd_client_plugin>(name);
}

ARK_EXPORT_FUNC void DllExitPlugin(plugin_manager* manager) {
manager->unregister_plugin<etcd_client_plugin>();
}

void etcd_client_plugin::install() {
ARK_REGISTER_MODULE(etcd_client_module, etcd_client_module_impl);
if (!register_module(detail::make_etcd_client_module(), module_update::disabled))
{
throw std::runtime_error("Etcd Client module registration rejected");
}
}

void etcd_client_plugin::uninstall() {
ARK_UNREGISTER_MODULE(etcd_client_module, etcd_client_module_impl);
if (!unregister_module<etcd_client_module>())
{
throw std::runtime_error("Etcd Client module unregistration rejected");
}
}

} // namespace ark
12 changes: 9 additions & 3 deletions src/plugins/etcd_client/etcd_client_plugin.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
#include "ark/plugin.hpp"
#include "ark/plugin_manager.hpp"
#pragma once

#include "ark/plugin_base.hpp"

namespace ark {

ARK_DECLARE_PLUGIN(etcd_client_plugin)
class etcd_client_plugin final : public plugin_base<etcd_client_plugin>
{
public:
void install() override;
void uninstall() override;
};

} // namespace ark
4 changes: 2 additions & 2 deletions tests/ci/install-package.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ include(cmake/ark_install.cmake)
const text = readFileSync(file, 'utf8');
for (const forbidden of [root, producer, build, prefix]) assert.ok(!text.includes(forbidden), `${file}: ${forbidden}`);
}
for (const name of ['mysql/mysql_module.hpp', 'kernel/kernel_plugin.hpp', 'physic/physic_module_impl.hpp', 'application_manifest.hpp']) {
for (const name of ['mysql/mysql_module.hpp', 'kernel/kernel_plugin.hpp', 'etcd_client/etcd_client_plugin.hpp', 'etcd_client/etcd_client_module_impl.hpp', 'physic/physic_module_impl.hpp', 'application_manifest.hpp']) {
assert.ok(existsSync(join(relocated, 'include/ark', name)), name);
}
for (const name of ['mysql/mysql_plugin.hpp', 'bus/bus_config_parser.hpp', 'http/http_plugin.hpp', 'net/http_client_module_impl.hpp', 'net/http_client_factory.hpp', 'kernel/kernel_factory.hpp', 'configuration_reader.hpp']) {
for (const name of ['mysql/mysql_plugin.hpp', 'bus/bus_config_parser.hpp', 'http/http_plugin.hpp', 'net/http_client_module_impl.hpp', 'net/http_client_factory.hpp', 'kernel/kernel_factory.hpp', 'etcd_client/etcd_client_factory.hpp', 'configuration_reader.hpp']) {
assert.equal(existsSync(join(relocated, 'include/ark', name)), false, name);
}
rmSync(producer, { recursive: true });
Expand Down
Loading
Loading