Skip to main content

drasi_bootstrap_mysql/
lib.rs

1#![allow(unexpected_cfgs)]
2// Copyright 2025 The Drasi Authors.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16//! MySQL bootstrap provider for Drasi.
17//!
18//! Provides an initial snapshot of MySQL tables when a query subscribes
19//! with bootstrap enabled.
20
21mod config;
22pub mod descriptor;
23mod mysql;
24#[cfg(test)]
25mod tests;
26
27pub use config::{MySqlBootstrapConfig, TableKeyConfig};
28
29use async_trait::async_trait;
30use drasi_lib::bootstrap::{
31    BootstrapContext, BootstrapProvider, BootstrapRequest, BootstrapResult,
32};
33use drasi_lib::channels::BootstrapEventSender;
34
35#[derive(Clone)]
36pub struct MySqlBootstrapProvider {
37    config: MySqlBootstrapConfig,
38}
39
40impl MySqlBootstrapProvider {
41    pub fn new(config: MySqlBootstrapConfig) -> Self {
42        Self { config }
43    }
44
45    pub fn builder() -> MySqlBootstrapBuilder {
46        MySqlBootstrapBuilder::new()
47    }
48}
49
50#[async_trait]
51impl BootstrapProvider for MySqlBootstrapProvider {
52    async fn bootstrap(
53        &self,
54        request: BootstrapRequest,
55        context: &BootstrapContext,
56        event_tx: BootstrapEventSender,
57        settings: Option<&drasi_lib::config::SourceSubscriptionSettings>,
58    ) -> anyhow::Result<BootstrapResult> {
59        let mut handler = mysql::MySqlBootstrapHandler::new(self.config.clone());
60        handler.execute(request, context, event_tx, settings).await
61    }
62}
63
64/// Builder for MySQL bootstrap provider configuration.
65///
66/// Provides a fluent API for constructing MySQL bootstrap configurations.
67pub struct MySqlBootstrapBuilder {
68    host: String,
69    port: u16,
70    database: String,
71    user: String,
72    password: String,
73    tables: Vec<String>,
74    table_keys: Vec<TableKeyConfig>,
75}
76
77impl Default for MySqlBootstrapBuilder {
78    fn default() -> Self {
79        Self::new()
80    }
81}
82
83impl MySqlBootstrapBuilder {
84    pub fn new() -> Self {
85        Self {
86            host: "localhost".to_string(),
87            port: 3306,
88            database: String::new(),
89            user: String::new(),
90            password: String::new(),
91            tables: Vec::new(),
92            table_keys: Vec::new(),
93        }
94    }
95
96    pub fn with_host(mut self, host: impl Into<String>) -> Self {
97        self.host = host.into();
98        self
99    }
100
101    pub fn with_port(mut self, port: u16) -> Self {
102        self.port = port;
103        self
104    }
105
106    pub fn with_database(mut self, database: impl Into<String>) -> Self {
107        self.database = database.into();
108        self
109    }
110
111    pub fn with_user(mut self, user: impl Into<String>) -> Self {
112        self.user = user.into();
113        self
114    }
115
116    pub fn with_password(mut self, password: impl Into<String>) -> Self {
117        self.password = password.into();
118        self
119    }
120
121    pub fn with_tables(mut self, tables: Vec<String>) -> Self {
122        self.tables = tables;
123        self
124    }
125
126    pub fn add_table(mut self, table: impl Into<String>) -> Self {
127        self.tables.push(table.into());
128        self
129    }
130
131    pub fn with_table_keys(mut self, table_keys: Vec<TableKeyConfig>) -> Self {
132        self.table_keys = table_keys;
133        self
134    }
135
136    pub fn add_table_key(mut self, table_key: TableKeyConfig) -> Self {
137        self.table_keys.push(table_key);
138        self
139    }
140
141    pub fn build(self) -> anyhow::Result<MySqlBootstrapProvider> {
142        let config = MySqlBootstrapConfig {
143            host: self.host,
144            port: self.port,
145            database: self.database,
146            user: self.user,
147            password: self.password,
148            tables: self.tables,
149            table_keys: self.table_keys,
150        };
151        config.validate()?;
152        Ok(MySqlBootstrapProvider::new(config))
153    }
154}
155
156/// Dynamic plugin entry point.
157#[cfg(feature = "dynamic-plugin")]
158drasi_plugin_sdk::export_plugin!(
159    plugin_id = "mysql-bootstrap",
160    core_version = env!("CARGO_PKG_VERSION"),
161    lib_version = env!("CARGO_PKG_VERSION"),
162    plugin_version = env!("CARGO_PKG_VERSION"),
163    source_descriptors = [],
164    reaction_descriptors = [],
165    bootstrap_descriptors = [descriptor::MySqlBootstrapDescriptor],
166);