pgdog.git / summary / log / commit / refs
commit 20cc80928cbb2ed237bf0fbf23c7e29de375906f
Author: Lev Kokotov <lev.kokotov@gmail.com>
Date: Thu Jan 09 07:04:11 2025 +0000
save
docs/docs/features/index.md | 3 +-
docs/docs/features/plugins/index.md | 37 +++++++++++++++------
docs/docs/features/plugins/rust.md | 64 +++++++++++++++++++++++++++++++++++++
3 files changed, 93 insertions(+), 11 deletions(-)
diff --git a/docs/docs/features/index.md b/docs/docs/features/index.md
index 44f2e140..42f6f3e5 100644
--- a/docs/docs/features/index.md
+++ b/docs/docs/features/index.md
@@ -13,6 +13,7 @@ load balancing, healthchecks, and query routing have been battle-tested and work
|---------|-------------|-------|
| [Transaction mode](transaction-mode.md) | Multiplex transactions and servers, allowing for high reuse of PostgreSQL server connections. | ✔️ Good |
| [Load balancer](load-balancer.md) | Splits query traffic evenly across multiple databases. | 🔨 Work in progress |
-| [Healthcheks](healthchecks.md) | Periodically checks databases to ensure they can serve queries. | ✔️ Stable |
+| [Healthcheks](healthchecks.md) | Periodically checks databases to ensure they can serve queries. | ✔️ Good |
| [Live configuration reloading](../configuration/index.md) | Pooler configuration and users can be changed at runtime without restarting the pooler or breaking connections. | 🔨 Work in progress |
| [Sharding](sharding/index.md) | Automatic routing of queries using a sharding key to scale writes horizontally. | 🔨 Work in progress |
+| [Plugins](plugins/index.md) | Pluggable libraries to parse and route queries, loaded at runtime. | ✔️ Good |
diff --git a/docs/docs/features/plugins/index.md b/docs/docs/features/plugins/index.md
index 76219b85..1a814fba 100644
--- a/docs/docs/features/plugins/index.md
+++ b/docs/docs/features/plugins/index.md
@@ -2,7 +2,7 @@
One of features that make pgDog particularly powerful is its plugin system. Users of pgDog can write plugins
in any language and inject them inside the query router to direct query traffic, to rewrite queries, or to block
-them entirely and return a custom result.
+them entirely and return custom results.
## API
@@ -20,14 +20,14 @@ functions or initialize synchronization primitives, like mutexes.
This function has the following signature:
-=== "C/C++"
- ```c
- void pgdog_init();
- ```
=== "Rust"
```rust
pub extern "C" fn pgdog_init() {}
```
+=== "C/C++"
+ ```c
+ void pgdog_init();
+ ```
#### `pgdog_route_query`
@@ -38,17 +38,34 @@ expects the plugin to parse the query and provide a route.
This function has the following signature:
+=== "Rust"
+ ```rust
+ use pgdog_plugin::*;
+
+ pub extern "C" fn pgdog_route_query(Input query) -> Output {
+ Route::unknown()
+ }
+ ```
=== "C/C++"
```c
Route pgdog_route_query(Query query);
```
+
+
+#### `pgdog_fini`
+
+This function is called before the pooler is shut down. This allows plugins to perform any tasks, like saving
+some internal state to a durable medium.
+
+This function has the following signature:
+
=== "Rust"
```rust
- use pgdog_plugin::bindings;
-
- pub extern "C" fn pgdog_route_query(bindings::Query query) -> Route {
- Route::unknown()
- }
+ pub extern "C" fn pgdog_fini() {}
+ ```
+=== "C/C++"
+ ```c
+ void pgdog_fini();
```
## Examples
diff --git a/docs/docs/features/plugins/rust.md b/docs/docs/features/plugins/rust.md
index d46218cf..d7725c48 100644
--- a/docs/docs/features/plugins/rust.md
+++ b/docs/docs/features/plugins/rust.md
@@ -1 +1,65 @@
# Plugins in Rust
+
+Writing pgDog plugins in Rust has first class support built into the [`pgdog-plugin`](https://github.com/levkk/pgdog/tree/main/pgdog-plugin) crate. The crate acts
+as a bridge between plugins and pgDog internals, and provides safe methods for constructing C-compatible structs.
+
+## How it works
+
+For plugins to be trully dynamic, they have to be compiled into shared libraries (`.so` on Linux, `.dylib` on Mac). This way you can load arbitrary plugins into pgDog at runtime without having to recompile it. Since Rust doesn't have a stable [ABI](https://en.wikipedia.org/wiki/Application_binary_interface), we have to use the only stable ABI available to all programming languages: C.
+
+### C ABI
+
+Rust has great bindings for using (and exposing) C-compatible functions. You can learn more about this by reading the [`std::ffi`](https://doc.rust-lang.org/stable/std/ffi/index.html) documentation and other great sources like The Embedded Rust Book[^1].
+
+The [`pgdog-plugin`](https://github.com/levkk/pgdog/tree/main/pgdog-plugin) crate contains C [headers](https://github.com/levkk/pgdog/tree/main/pgdog-plugin/include) that define
+types and functions pgDog expects its plugins to use, with Rust bindings generated with [bindgen](https://docs.rs/bindgen/latest/bindgen/).
+
+[^1]: [https://docs.rust-embedded.org/book/interoperability/rust-with-c.html](https://docs.rust-embedded.org/book/interoperability/rust-with-c.html)
+
+
+## Getting started
+
+Create a new library crate with Cargo, like so:
+
+```bash
+cargo new --lib my_pgdog_plugin
+```
+
+Since plugins have to be C ABI compatible, you'll need to change the crate type to `cdylib` (C dynamic library).
+Edit your `Cargo.toml` and add the following:
+
+```toml
+[lib]
+crate-type = ["rlib", "cdylib"]
+```
+
+### Add `pgdog-plugin`
+
+To make building plugins easier, pgDog provides a crate that defines and implements the structs used by
+plugin functions.
+
+Before proceeding, add this crate to your dependencies:
+
+```bash
+cargo add pgdog-plugin
+```
+
+### Implement the API
+
+The [plugin API](../plugins/index.md) is pretty simple. For this tutorial, we'll implement the query routing function `pgdog_route_query`, which is called for every transaction pgDog receives.
+
+#### `pgdog_route_query`
+
+This function has the following signature:
+
+```rust
+use pgdog_plugin::*;
+
+pub extern "C" fn pgdog_route_query(input: Input) -> Output {
+ todo()
+}
+```
+
+## Learn more
+
+- [pgdog-routing](https://github.com/levkk/pgdog/tree/main/plugins/pgdog-routing) plugin
[parent: d5d847709866]