]> git.puffer.fish Git - matthieu/nova.git/commitdiff
add all in one binary
authorMatthieuCoder <matthieu@matthieu-dev.xyz>
Mon, 2 Jan 2023 20:14:27 +0000 (00:14 +0400)
committerMatthieuCoder <matthieu@matthieu-dev.xyz>
Mon, 2 Jan 2023 20:14:27 +0000 (00:14 +0400)
27 files changed:
Cargo.lock
Cargo.toml
exes/all/.gitignore [new file with mode: 0644]
exes/all/Cargo.toml [new file with mode: 0644]
exes/all/Makefile [new file with mode: 0644]
exes/all/build.rs [new file with mode: 0644]
exes/all/build/.gitkeep [new file with mode: 0644]
exes/all/main.go [new file with mode: 0644]
exes/all/src/lib.rs [new file with mode: 0644]
exes/cache/src/main.rs
exes/gateway/src/lib.rs [new file with mode: 0644]
exes/gateway/src/main.rs
exes/ratelimit/Cargo.toml
exes/ratelimit/src/lib.rs [new file with mode: 0644]
exes/ratelimit/src/main.rs
exes/rest/src/config.rs
exes/rest/src/lib.rs [new file with mode: 0644]
exes/rest/src/main.rs
exes/rest/src/ratelimit_client/mod.rs
exes/rest/src/ratelimit_client/remote_hashring.rs
exes/webhook/src/config.rs
exes/webhook/src/lib.rs [new file with mode: 0644]
exes/webhook/src/main.rs
go.mod
go.sum
libs/leash/src/lib.rs
libs/shared/src/nats.rs

index 08e01efe042cbfd3c1efd3469ef269db142f9b8c..025545f63a62eda7cc107895d237e84428251a55 100644 (file)
@@ -28,6 +28,27 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "all"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "cache",
+ "cbindgen",
+ "config",
+ "gateway",
+ "leash",
+ "libc",
+ "pretty_env_logger",
+ "ratelimit",
+ "rest",
+ "serde",
+ "serde_json",
+ "shared",
+ "tokio",
+ "webhook",
+]
+
 [[package]]
 name = "android_system_properties"
 version = "0.1.5"
@@ -269,6 +290,25 @@ dependencies = [
  "twilight-model",
 ]
 
+[[package]]
+name = "cbindgen"
+version = "0.24.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb"
+dependencies = [
+ "clap",
+ "heck",
+ "indexmap",
+ "log",
+ "proc-macro2",
+ "quote",
+ "serde",
+ "serde_json",
+ "syn",
+ "tempfile",
+ "toml",
+]
+
 [[package]]
 name = "cc"
 version = "1.0.78"
@@ -297,6 +337,30 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "clap"
+version = "3.2.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
+dependencies = [
+ "atty",
+ "bitflags",
+ "clap_lex",
+ "indexmap",
+ "strsim",
+ "termcolor",
+ "textwrap",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
+dependencies = [
+ "os_str_bytes",
+]
+
 [[package]]
 name = "codespan-reporting"
 version = "0.11.1"
@@ -1415,6 +1479,12 @@ dependencies = [
  "hashbrown",
 ]
 
+[[package]]
+name = "os_str_bytes"
+version = "6.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
+
 [[package]]
 name = "parking_lot"
 version = "0.12.1"
@@ -2359,6 +2429,12 @@ dependencies = [
  "sha2 0.10.6",
 ]
 
+[[package]]
+name = "textwrap"
+version = "0.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
+
 [[package]]
 name = "thiserror"
 version = "1.0.38"
index 785bb95fa0e927e0d97be2803f9428c035ff6f85..6fd4694689c0bca58609537108b8566bcb2efc83 100644 (file)
@@ -5,6 +5,7 @@ members = [
     "exes/rest/",\r
     "exes/webhook/",\r
     "exes/ratelimit/",\r
+    "exes/all",\r
 \r
     "libs/proto/",\r
     "libs/shared/",\r
diff --git a/exes/all/.gitignore b/exes/all/.gitignore
new file mode 100644 (file)
index 0000000..27531c7
--- /dev/null
@@ -0,0 +1,3 @@
+build/*
+!build/.gitkeep
+config/
\ No newline at end of file
diff --git a/exes/all/Cargo.toml b/exes/all/Cargo.toml
new file mode 100644 (file)
index 0000000..d6976ef
--- /dev/null
@@ -0,0 +1,31 @@
+[package]
+name = "all"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+libc = "0.2.139"
+leash = { path = "../../libs/leash" }
+shared = { path = "../../libs/shared" }
+
+cache = { path = "../cache" }
+gateway = { path = "../gateway" }
+ratelimit = { path = "../ratelimit" }
+rest = { path = "../rest" }
+webhook = { path = "../webhook" }
+
+tokio = { version = "1.23.0", features = ["full"] }
+serde = "1.0.152"
+serde_json = "1.0.91"
+anyhow = "1.0.68"
+
+config = "0.13.3"
+pretty_env_logger = "0.4.0"
+
+[lib]
+crate-type = ["cdylib"]
+
+[build-dependencies]
+cbindgen = "0.24.3"
\ No newline at end of file
diff --git a/exes/all/Makefile b/exes/all/Makefile
new file mode 100644 (file)
index 0000000..07c02d9
--- /dev/null
@@ -0,0 +1,14 @@
+clean:
+       rm ./build/libhello.so
+
+library:
+       cargo build --release
+
+build: library
+       cp ../../target/release/liball.so ./build
+       go build -ldflags="-r build" -o build/all
+
+all: library build
+
+run: all
+       ./build/all
diff --git a/exes/all/build.rs b/exes/all/build.rs
new file mode 100644 (file)
index 0000000..e779d53
--- /dev/null
@@ -0,0 +1,26 @@
+extern crate cbindgen;
+
+use std::env;
+use std::path::PathBuf;
+use cbindgen::{Config, Language};
+
+
+fn main() {
+    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
+
+    let package_name = env::var("CARGO_PKG_NAME").unwrap();
+    let output_file = PathBuf::from("./build")
+        .join(format!("{}.h", package_name))
+        .display()
+        .to_string();
+
+    let config = Config {
+        namespace: Some(String::from("ffi")),
+        language: Language::C,
+        ..Default::default()
+    };
+
+    cbindgen::generate_with_config(&crate_dir, config)
+      .unwrap()
+      .write_to_file(&output_file);
+}
diff --git a/exes/all/build/.gitkeep b/exes/all/build/.gitkeep
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/exes/all/main.go b/exes/all/main.go
new file mode 100644 (file)
index 0000000..0d15450
--- /dev/null
@@ -0,0 +1,72 @@
+package main
+
+/*
+#cgo LDFLAGS: -Lbuild -lall
+#include "./build/all.h"
+*/
+import "C"
+
+import (
+       "fmt"
+       "os"
+       "os/signal"
+       "syscall"
+       "time"
+
+       "github.com/Jeffail/gabs"
+       "github.com/alicebob/miniredis/v2"
+
+       server "github.com/nats-io/nats-server/v2/server"
+)
+
+func main() {
+       // Intialise les logs de la librarie Rust
+       C.init_logs()
+       // Charge la configuration
+       str := C.GoString(C.load_config())
+
+       // Démarre une instance MiniRedis
+       mr := miniredis.NewMiniRedis()
+       err := mr.Start()
+
+       if err != nil {
+               panic(err)
+       }
+
+       // Démarre un serveur Nats
+       opts := &server.Options{}
+       opts.Host = "0.0.0.0"
+       ns, err := server.NewServer(opts)
+
+       if err != nil {
+               panic(err)
+       }
+
+       go ns.Start()
+
+       if !ns.ReadyForConnections(4 * time.Second) {
+               panic("not ready for connection")
+       }
+
+       // Edite le json de configuration donné
+       // Et injecte la configuration des servers Nats et MiniRedis
+       json, _ := gabs.ParseJSON([]byte(str))
+       json.Set(fmt.Sprintf("redis://%s", mr.Addr()), "redis", "url")
+       json.Set("localhost", "nats", "host")
+       json.Set(1, "webhook", "discord", "client_id")
+
+       // Démarre une instance de nova
+       instance := C.start_instance(C.CString(json.String()))
+
+       // Wait for a SIGINT
+       c := make(chan os.Signal, 1)
+       signal.Notify(c,
+               syscall.SIGHUP,
+               syscall.SIGINT,
+               syscall.SIGTERM,
+               syscall.SIGQUIT)
+       <-c
+
+       println("Arret de nova all in one")
+       C.stop_instance(instance)
+}
diff --git a/exes/all/src/lib.rs b/exes/all/src/lib.rs
new file mode 100644 (file)
index 0000000..f6b527d
--- /dev/null
@@ -0,0 +1,137 @@
+extern crate libc;
+use anyhow::Result;
+use config::{Config, Environment, File};
+use gateway::GatewayServer;
+use leash::Component;
+use ratelimit::RatelimiterServerComponent;
+use rest::ReverseProxyServer;
+use serde::de::DeserializeOwned;
+use serde_json::Value;
+use shared::{config::Settings, log::info};
+use std::{
+    env,
+    ffi::{CStr, CString},
+    time::Duration,
+};
+use tokio::{
+    runtime::Runtime,
+    sync::oneshot::{self, Sender},
+    task::JoinHandle,
+};
+use webhook::WebhookServer;
+
+pub struct AllInOneInstance {
+    pub stop: Sender<Sender<()>>,
+    pub runtime: Runtime,
+}
+
+fn load_settings_for<T: Default + DeserializeOwned + Clone>(
+    settings: &str,
+    name: &str,
+) -> Result<Settings<T>> {
+    let value: Value = serde_json::from_str(settings)?;
+    let section: T = serde_json::from_value(value.get(name).unwrap().to_owned())?;
+    let mut settings: Settings<T> = serde_json::from_value(value)?;
+    settings.config = section;
+
+    Ok(settings)
+}
+
+// Start a component
+async fn start_component<T: Component>(
+    settings: String,
+    aio: &mut Vec<Sender<()>>,
+) -> JoinHandle<()> {
+    let name = T::SERVICE_NAME;
+    let instance = T::new();
+
+    let (stop, signal) = oneshot::channel();
+
+    aio.push(stop);
+
+    tokio::spawn(async move {
+        let config = load_settings_for::<<T as Component>::Config>(&settings, name).unwrap();
+        instance.start(config, signal).await.unwrap();
+    })
+}
+
+#[no_mangle]
+/// Loads the config json using the nova shared config loader
+pub extern "C" fn load_config() -> *const libc::c_char {
+    let mut builder = Config::builder();
+
+    builder = builder.add_source(File::with_name("config/default"));
+    let mode = env::var("ENV").unwrap_or_else(|_| "development".into());
+    info!("Configuration Environment: {}", mode);
+
+    builder = builder.add_source(File::with_name(&format!("config/{}", mode)).required(false));
+    builder = builder.add_source(File::with_name("config/local").required(false));
+
+    let env = Environment::with_prefix("NOVA").separator("__");
+    // we can configure each component using environment variables
+    builder = builder.add_source(env);
+
+    let config: Value = builder.build().unwrap().try_deserialize().unwrap();
+    let s = serde_json::to_string(&config).unwrap();
+
+    let c_str_song = CString::new(s).unwrap();
+    c_str_song.into_raw()
+}
+
+#[no_mangle]
+/// Initialise les logs des composants de nova
+/// Utilise la crate `pretty_log_env`
+pub extern "C" fn init_logs() {
+    pretty_env_logger::init();
+}
+
+#[no_mangle]
+/// Stops a nova instance
+pub unsafe extern "C" fn stop_instance(instance: *mut AllInOneInstance) {
+    let instance = Box::from_raw(instance);
+    let (tell_ready, ready) = oneshot::channel();
+    instance.stop.send(tell_ready).unwrap();
+    ready.blocking_recv().unwrap();
+    instance.runtime.shutdown_timeout(Duration::from_secs(5));
+}
+
+#[no_mangle]
+/// Initialized a new nova instance and an async runtime (tokio reactor)
+/// Dont forget to stop this instance using `stop_instance`
+pub extern "C" fn start_instance(config: *const libc::c_char) -> *mut AllInOneInstance {
+    let buf_name = unsafe { CStr::from_ptr(config).to_bytes() };
+    let settings = String::from_utf8(buf_name.to_vec()).unwrap();
+    let (stop, trigger_stop) = oneshot::channel();
+
+    // Initialize a tokio runtime
+    let rt = Runtime::new().unwrap();
+    rt.block_on(async move {
+        // Start the gateway server
+
+        let mut aio = vec![];
+        let mut handles = vec![];
+
+        // Start components
+        handles.push(start_component::<GatewayServer>(settings.clone(), &mut aio).await);
+        handles
+            .push(start_component::<RatelimiterServerComponent>(settings.clone(), &mut aio).await);
+        handles.push(start_component::<ReverseProxyServer>(settings.clone(), &mut aio).await);
+        handles.push(start_component::<WebhookServer>(settings.clone(), &mut aio).await);
+
+        // wait for exit
+        let done: Sender<()> = trigger_stop.await.unwrap();
+
+        // Tell all the threads to stop.
+        while let Some(stop_signal) = aio.pop() {
+            stop_signal.send(()).unwrap();
+        }
+
+        // Wait for all the threads to finish.
+        while let Some(handle) = handles.pop() {
+            handle.await.unwrap();
+        }
+
+        done.send(()).unwrap();
+    });
+    Box::into_raw(Box::new(AllInOneInstance { stop, runtime: rt }))
+}
index 312f960664094ff3337d5d14aac1d74ce3ea69c6..5240a6a32d8507585825ec34a46fa082a67b2c17 100644 (file)
@@ -43,7 +43,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
     let settings: Settings<CacheConfiguration> = Settings::new("cache").unwrap();
     info!("loaded configuration: {:?}", settings);
     let nats =
-        Into::<Pin<Box<dyn Future<Output = anyhow::Result<Client>>>>>::into(settings.nats).await?;
+        Into::<Pin<Box<dyn Future<Output = anyhow::Result<Client>> + Send>>>::into(settings.nats).await?;
     // let redis: redis::Client = settings.redis.into();
 
     let mut cache = Cache::default();
diff --git a/exes/gateway/src/lib.rs b/exes/gateway/src/lib.rs
new file mode 100644 (file)
index 0000000..d7a4cee
--- /dev/null
@@ -0,0 +1,87 @@
+use config::GatewayConfig;
+use leash::{AnyhowResultFuture, Component};
+use shared::{
+    config::Settings,
+    log::{debug, info},
+    nats_crate::Client,
+    payloads::{CachePayload, DispatchEventTagged, Tracing},
+};
+use std::{convert::TryFrom, pin::Pin};
+use tokio::sync::oneshot;
+use twilight_gateway::{Event, Shard};
+pub mod config;
+use futures::FutureExt;
+use futures::{select, Future, StreamExt};
+use twilight_model::gateway::event::DispatchEvent;
+
+pub struct GatewayServer {}
+impl Component for GatewayServer {
+    type Config = GatewayConfig;
+    const SERVICE_NAME: &'static str = "gateway";
+
+    fn start(
+        &self,
+        settings: Settings<Self::Config>,
+        stop: oneshot::Receiver<()>,
+    ) -> AnyhowResultFuture<()> {
+        Box::pin(async move {
+            let (shard, mut events) = Shard::builder(settings.token.to_owned(), settings.intents)
+                .shard(settings.shard, settings.shard_total)?
+                .build();
+
+            let nats = Into::<Pin<Box<dyn Future<Output = anyhow::Result<Client>> + Send>>>::into(
+                settings.nats,
+            )
+            .await?;
+
+            shard.start().await?;
+
+            let mut stop = stop.fuse();
+            loop {
+                select! {
+                    event = events.next().fuse() => {
+                        if let Some(event) = event {
+                            match event {
+                                Event::Ready(ready) => {
+                                    info!("Logged in as {}", ready.user.name);
+                                }
+
+                                _ => {
+                                    let name = event.kind().name();
+                                    if let Ok(dispatch_event) = DispatchEvent::try_from(event) {
+                                        let data = CachePayload {
+                                            tracing: Tracing {
+                                                node_id: "".to_string(),
+                                                span: None,
+                                            },
+                                            data: DispatchEventTagged {
+                                                data: dispatch_event,
+                                            },
+                                        };
+                                        let value = serde_json::to_string(&data)?;
+                                        debug!("nats send: {}", value);
+                                        let bytes = bytes::Bytes::from(value);
+                                        nats.publish(format!("nova.cache.dispatch.{}", name.unwrap()), bytes)
+                                            .await?;
+                                    }
+                                }
+                            }
+                        } else {
+                            break
+                        }
+                    },
+                    _ = stop => break
+                };
+            }
+
+            info!("stopping shard...");
+            shard.shutdown();
+
+            Ok(())
+        })
+    }
+
+    fn new() -> Self {
+        Self {}
+    }
+}
index f2a4f936b24fe42878d349415ed2ff0de4c97a01..2e18f9c2051ae34bb633c1b9c95586141b306403 100644 (file)
@@ -1,89 +1,4 @@
-use config::GatewayConfig;
-use leash::{ignite, AnyhowResultFuture, Component};
-use shared::{
-    config::Settings,
-    log::{debug, info},
-    nats_crate::Client,
-    payloads::{CachePayload, DispatchEventTagged, Tracing},
-};
-use tokio::sync::oneshot;
-use std::{convert::TryFrom, pin::Pin};
-use twilight_gateway::{Event, Shard};
-mod config;
-use futures::{Future, StreamExt, select};
-use twilight_model::gateway::event::DispatchEvent;
-use futures::FutureExt;
-
-struct GatewayServer {}
-impl Component for GatewayServer {
-    type Config = GatewayConfig;
-    const SERVICE_NAME: &'static str = "gateway";
-
-    fn start(
-        &self,
-        settings: Settings<Self::Config>,
-        stop: oneshot::Receiver<()>,
-    ) -> AnyhowResultFuture<()> {
-        Box::pin(async move {
-            let (shard, mut events) = Shard::builder(settings.token.to_owned(), settings.intents)
-                .shard(settings.shard, settings.shard_total)?
-                .build();
-
-            let nats =
-                Into::<Pin<Box<dyn Future<Output = anyhow::Result<Client>>>>>::into(settings.nats)
-                    .await?;
-
-            shard.start().await?;
-
-            let mut stop = stop.fuse();
-            loop {
-
-                select! {
-                    event = events.next().fuse() => {
-                        if let Some(event) = event {
-                            match event {
-                                Event::Ready(ready) => {
-                                    info!("Logged in as {}", ready.user.name);
-                                }
-            
-                                _ => {
-                                    let name = event.kind().name();
-                                    if let Ok(dispatch_event) = DispatchEvent::try_from(event) {
-                                        let data = CachePayload {
-                                            tracing: Tracing {
-                                                node_id: "".to_string(),
-                                                span: None,
-                                            },
-                                            data: DispatchEventTagged {
-                                                data: dispatch_event,
-                                            },
-                                        };
-                                        let value = serde_json::to_string(&data)?;
-                                        debug!("nats send: {}", value);
-                                        let bytes = bytes::Bytes::from(value);
-                                        nats.publish(format!("nova.cache.dispatch.{}", name.unwrap()), bytes)
-                                            .await?;
-                                    }
-                                }
-                            }
-                        } else {
-                            break
-                        }
-                    },
-                    _ = stop => break
-                };
-            }
-
-            info!("stopping shard...");
-            shard.shutdown();
-
-            Ok(())
-        })
-    }
-
-    fn new() -> Self {
-        Self {}
-    }
-}
+use leash::ignite;
+use gateway::GatewayServer;
 
 ignite!(GatewayServer);
index a28d2d0c24fbf240585d01de85856f09079964e4..82ca9f609ca82767a89146d38d53cc64a242a036 100644 (file)
@@ -18,4 +18,4 @@ futures-util = "0.3.17"
 tracing = "*"
 serde_json = { version = "1.0" }
 tonic = "0.8.3"
-tokio-stream = "0.1.11"
\ No newline at end of file
+tokio-stream = "0.1.11"
diff --git a/exes/ratelimit/src/lib.rs b/exes/ratelimit/src/lib.rs
new file mode 100644 (file)
index 0000000..6d6d608
--- /dev/null
@@ -0,0 +1,45 @@
+use std::net::ToSocketAddrs;
+
+use futures_util::FutureExt;
+use grpc::RLServer;
+use leash::{AnyhowResultFuture, Component};
+use proto::nova::ratelimit::ratelimiter::ratelimiter_server::RatelimiterServer;
+use redis_global_local_bucket_ratelimiter::RedisGlobalLocalBucketRatelimiter;
+use shared::{config::Settings, redis_crate::Client};
+use tokio::sync::oneshot;
+use tonic::transport::Server;
+
+mod grpc;
+mod redis_global_local_bucket_ratelimiter;
+
+pub struct RatelimiterServerComponent {}
+impl Component for RatelimiterServerComponent {
+    type Config = ();
+    const SERVICE_NAME: &'static str = "ratelimiter";
+
+    fn start(
+        &self,
+        settings: Settings<Self::Config>,
+        stop: oneshot::Receiver<()>,
+    ) -> AnyhowResultFuture<()> {
+        Box::pin(async move {
+            // let config = Arc::new(settings.config);
+            let redis: Client = settings.redis.into();
+            let server = RLServer::new(RedisGlobalLocalBucketRatelimiter::new(redis.into()));
+
+            Server::builder()
+                .add_service(RatelimiterServer::new(server))
+                .serve_with_shutdown(
+                    "0.0.0.0:8093".to_socket_addrs().unwrap().next().unwrap(),
+                    stop.map(|_| ()),
+                )
+                .await?;
+
+            Ok(())
+        })
+    }
+
+    fn new() -> Self {
+        Self {}
+    }
+}
index 0ceded275f100a9987abf043bd96fca69fee0500..2de812b531d439e6050b3b483277db0f42267f3c 100644 (file)
@@ -1,47 +1,4 @@
-use std::net::ToSocketAddrs;
-
-use futures_util::FutureExt;
-use grpc::RLServer;
-use leash::{ignite, AnyhowResultFuture, Component};
-use proto::nova::ratelimit::ratelimiter::ratelimiter_server::RatelimiterServer;
-use redis_global_local_bucket_ratelimiter::RedisGlobalLocalBucketRatelimiter;
-use shared::{config::Settings, redis_crate::Client};
-use tokio::sync::oneshot;
-use tonic::transport::Server;
-
-mod grpc;
-mod redis_global_local_bucket_ratelimiter;
-
-struct RatelimiterServerComponent {}
-impl Component for RatelimiterServerComponent {
-    type Config = ();
-    const SERVICE_NAME: &'static str = "ratelimiter";
-
-    fn start(
-        &self,
-        settings: Settings<Self::Config>,
-        stop: oneshot::Receiver<()>,
-    ) -> AnyhowResultFuture<()> {
-        Box::pin(async move {
-            // let config = Arc::new(settings.config);
-            let redis: Client = settings.redis.into();
-            let server = RLServer::new(RedisGlobalLocalBucketRatelimiter::new(redis.into()));
-
-            Server::builder()
-                .add_service(RatelimiterServer::new(server))
-                .serve_with_shutdown(
-                    "0.0.0.0:8080".to_socket_addrs().unwrap().next().unwrap(),
-                    stop.map(|_| ()),
-                )
-                .await?;
-
-            Ok(())
-        })
-    }
-
-    fn new() -> Self {
-        Self {}
-    }
-}
+use leash::ignite;
+use ratelimit::RatelimiterServerComponent;
 
 ignite!(RatelimiterServerComponent);
index 5c2698b316baa67aa3a9849caeb90e8d30a92378..4e27a308aca36ffa270e4d35649bcc85e1182928 100644 (file)
@@ -2,7 +2,7 @@ use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
 use serde::Deserialize;
 
 fn default_listening_address() -> SocketAddr {
-    SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 8080))
+    SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 8090))
 }
 
 #[derive(Debug, Deserialize, Clone)]
diff --git a/exes/rest/src/lib.rs b/exes/rest/src/lib.rs
new file mode 100644 (file)
index 0000000..02721cc
--- /dev/null
@@ -0,0 +1,67 @@
+use config::ReverseProxyConfig;
+
+use handler::handle_request;
+use hyper::{
+    server::conn::AddrStream,
+    service::{make_service_fn, service_fn},
+    Body, Client, Request, Server,
+};
+use hyper_tls::HttpsConnector;
+use leash::{AnyhowResultFuture, Component};
+use shared::config::Settings;
+use std::{convert::Infallible, sync::Arc};
+use tokio::sync::oneshot;
+
+mod config;
+mod handler;
+mod ratelimit_client;
+
+pub struct ReverseProxyServer {}
+impl Component for ReverseProxyServer {
+    type Config = ReverseProxyConfig;
+    const SERVICE_NAME: &'static str = "rest";
+
+    fn start(
+        &self,
+        settings: Settings<Self::Config>,
+        stop: oneshot::Receiver<()>,
+    ) -> AnyhowResultFuture<()> {
+        Box::pin(async move {
+            // Client to the remote ratelimiters
+            let ratelimiter = ratelimit_client::RemoteRatelimiter::new();
+            let client = Client::builder().build(HttpsConnector::new());
+
+            let token = Arc::new(settings.discord.token.clone());
+            let service_fn = make_service_fn(move |_: &AddrStream| {
+                let client = client.clone();
+                let ratelimiter = ratelimiter.clone();
+                let token = token.clone();
+                async move {
+                    Ok::<_, Infallible>(service_fn(move |request: Request<Body>| {
+                        let client = client.clone();
+                        let ratelimiter = ratelimiter.clone();
+                        let token = token.clone();
+                        async move {
+                            let token = token.as_str();
+                            handle_request(client, ratelimiter, token, request).await
+                        }
+                    }))
+                }
+            });
+
+            let server = Server::bind(&settings.config.server.listening_adress).serve(service_fn);
+
+            server
+                .with_graceful_shutdown(async {
+                    stop.await.expect("should not fail");
+                })
+                .await?;
+
+            Ok(())
+        })
+    }
+
+    fn new() -> Self {
+        Self {}
+    }
+}
\ No newline at end of file
index 07d835c2247dfadc9157aa42e425e0d253a60916..fe8ada759ab1ec131bd00d7f134ab2aed31d7770 100644 (file)
@@ -1,69 +1,4 @@
-use config::ReverseProxyConfig;
-
-use handler::handle_request;
-use hyper::{
-    server::conn::AddrStream,
-    service::{make_service_fn, service_fn},
-    Body, Client, Request, Server,
-};
-use hyper_tls::HttpsConnector;
-use leash::{ignite, AnyhowResultFuture, Component};
-use shared::config::Settings;
-use std::{convert::Infallible, sync::Arc};
-use tokio::sync::oneshot;
-
-mod config;
-mod handler;
-mod ratelimit_client;
-
-struct ReverseProxyServer {}
-impl Component for ReverseProxyServer {
-    type Config = ReverseProxyConfig;
-    const SERVICE_NAME: &'static str = "rest";
-
-    fn start(
-        &self,
-        settings: Settings<Self::Config>,
-        stop: oneshot::Receiver<()>,
-    ) -> AnyhowResultFuture<()> {
-        Box::pin(async move {
-            // Client to the remote ratelimiters
-            let ratelimiter = ratelimit_client::RemoteRatelimiter::new();
-            let client = Client::builder().build(HttpsConnector::new());
-
-            let token = Arc::new(settings.discord.token.clone());
-            let service_fn = make_service_fn(move |_: &AddrStream| {
-                let client = client.clone();
-                let ratelimiter = ratelimiter.clone();
-                let token = token.clone();
-                async move {
-                    Ok::<_, Infallible>(service_fn(move |request: Request<Body>| {
-                        let client = client.clone();
-                        let ratelimiter = ratelimiter.clone();
-                        let token = token.clone();
-                        async move {
-                            let token = token.as_str();
-                            handle_request(client, ratelimiter, token, request).await
-                        }
-                    }))
-                }
-            });
-
-            let server = Server::bind(&settings.config.server.listening_adress).serve(service_fn);
-
-            server
-                .with_graceful_shutdown(async {
-                    stop.await.expect("should not fail");
-                })
-                .await?;
-
-            Ok(())
-        })
-    }
-
-    fn new() -> Self {
-        Self {}
-    }
-}
+use leash::ignite;
+use rest::ReverseProxyServer;
 
 ignite!(ReverseProxyServer);
index 87737dd5b9a92c74993d30b14b3fed5d03da44a3..afaf2b7446ff673da2e895897188f18f73e018fb 100644 (file)
@@ -30,14 +30,14 @@ impl Drop for RemoteRatelimiter {
 impl RemoteRatelimiter {
     async fn get_ratelimiters(&self) -> Result<(), anyhow::Error> {
         // get list of dns responses
-        let responses = dns_lookup::lookup_host("ratelimit")
+        /*let responses = dns_lookup::lookup_host("localhost")
             .unwrap()
             .into_iter()
-            .map(|f| f.to_string());
+            .map(|f| f.to_string());*/
 
         let mut write = self.remotes.write().await;
 
-        for ip in responses {
+        for ip in ["localhost"] {
             let a = VNode::new(ip.into()).await?;
             write.add(a.clone());
         }
index b9f780036fc8aba08db65ae0f03c0b464e53142c..4e3fa06d994bc099665f863bc0f2fe70712518a5 100644 (file)
@@ -34,7 +34,7 @@ impl Hash for VNode {
 
 impl VNode {
     pub async fn new(address: String) -> Result<Self, tonic::transport::Error> {
-        let client = RatelimiterClient::connect(format!("http://{}:8080", address.clone())).await?;
+        let client = RatelimiterClient::connect(format!("http://{}:8093", address.clone())).await?;
 
         Ok(VNode { client, address })
     }
index e98de137ae4363248f4a008a88e54e1fcee0c322..56a9b784fffd6cdb2870a8cfd2ef07de7de4b39d 100644 (file)
@@ -4,7 +4,7 @@ use ed25519_dalek::PublicKey;
 use serde::{Deserialize, Deserializer};
 
 fn default_listening_address() -> SocketAddr {
-    SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 8080))
+    SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 8091))
 }
 
 #[derive(Debug, Deserialize, Clone, Copy)]
diff --git a/exes/webhook/src/lib.rs b/exes/webhook/src/lib.rs
new file mode 100644 (file)
index 0000000..13a4e60
--- /dev/null
@@ -0,0 +1,54 @@
+mod config;
+mod handler;
+use std::{future::Future, pin::Pin};
+
+use crate::{
+    config::WebhookConfig,
+    handler::{handler::WebhookService, make_service::MakeSvc},
+};
+use hyper::Server;
+use leash::{AnyhowResultFuture, Component};
+use shared::{config::Settings, log::info, nats_crate::Client};
+use tokio::sync::oneshot;
+
+#[derive(Clone, Copy)]
+pub struct WebhookServer {}
+
+impl Component for WebhookServer {
+    type Config = WebhookConfig;
+    const SERVICE_NAME: &'static str = "webhook";
+
+    fn start(
+        &self,
+        settings: Settings<Self::Config>,
+        stop: oneshot::Receiver<()>,
+    ) -> AnyhowResultFuture<()> {
+        Box::pin(async move {
+            info!("Starting server on {}", settings.server.listening_adress);
+
+            let bind = settings.server.listening_adress;
+            info!("NAts connected!");
+            let nats =
+                Into::<Pin<Box<dyn Future<Output = anyhow::Result<Client>> + Send>>>::into(settings.nats)
+
+                    .await?;
+
+            let make_service = MakeSvc::new(WebhookService {
+                config: settings.config,
+                nats: nats.clone(),
+            });
+
+            let server = Server::bind(&bind).serve(make_service);
+
+            server.with_graceful_shutdown(async {
+                stop.await.expect("should not fail");
+            }).await?;
+
+            Ok(())
+        })
+    }
+
+    fn new() -> Self {
+        Self {}
+    }
+}
\ No newline at end of file
index 0215e511e112459f3a306684aa339fe8df322bd6..f53172558ca50d64363e1f3cbe1a0f1315e34c06 100644 (file)
@@ -1,54 +1,4 @@
-mod config;
-mod handler;
-use std::{future::Future, pin::Pin};
-
-use crate::{
-    config::WebhookConfig,
-    handler::{handler::WebhookService, make_service::MakeSvc},
-};
-use hyper::Server;
-use leash::{ignite, AnyhowResultFuture, Component};
-use shared::{config::Settings, log::info, nats_crate::Client};
-use tokio::sync::oneshot;
-
-#[derive(Clone, Copy)]
-struct WebhookServer {}
-
-impl Component for WebhookServer {
-    type Config = WebhookConfig;
-    const SERVICE_NAME: &'static str = "webhook";
-
-    fn start(
-        &self,
-        settings: Settings<Self::Config>,
-        stop: oneshot::Receiver<()>,
-    ) -> AnyhowResultFuture<()> {
-        Box::pin(async move {
-            info!("Starting server on {}", settings.server.listening_adress);
-
-            let bind = settings.server.listening_adress;
-            let nats =
-                Into::<Pin<Box<dyn Future<Output = anyhow::Result<Client>>>>>::into(settings.nats)
-                    .await?;
-
-            let make_service = MakeSvc::new(WebhookService {
-                config: settings.config,
-                nats: nats.clone(),
-            });
-
-            let server = Server::bind(&bind).serve(make_service);
-
-            server.with_graceful_shutdown(async {
-                stop.await.expect("should not fail");
-            }).await?;
-
-            Ok(())
-        })
-    }
-
-    fn new() -> Self {
-        Self {}
-    }
-}
+use leash::ignite;
+use webhook::WebhookServer;
 
 ignite!(WebhookServer);
diff --git a/go.mod b/go.mod
index 46fd371e794932aea056e85a22cdf43867b898ce..675647150be271d3d876c290539a92fa49c000b7 100644 (file)
--- a/go.mod
+++ b/go.mod
@@ -3,23 +3,30 @@ module github.com/discordnova/nova
 go 1.16
 
 require (
+       github.com/Jeffail/gabs v1.4.0
        github.com/Microsoft/go-winio v0.5.1 // indirect
        github.com/ProtonMail/go-crypto v0.0.0-20210920160938-87db9fbc61c7 // indirect
+       github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
+       github.com/alicebob/miniredis v2.5.0+incompatible
+       github.com/alicebob/miniredis/v2 v2.23.1
        github.com/cespare/xxhash/v2 v2.1.2 // indirect
        github.com/go-git/go-git/v5 v5.4.2
+       github.com/gomodule/redigo v1.8.9 // indirect
        github.com/kevinburke/ssh_config v1.1.0 // indirect
        github.com/mattn/go-runewidth v0.0.13 // indirect
+       github.com/nats-io/gnatsd v1.4.1 // indirect
+       github.com/nats-io/nats-server v1.4.1
+       github.com/nats-io/nats-server/v2 v2.9.10
+       github.com/nats-io/nats-streaming-server v0.25.2
+       github.com/nats-io/nuid v1.0.1 // indirect
        github.com/olekukonko/tablewriter v0.0.5
        github.com/prometheus/client_golang v1.11.0
        github.com/prometheus/common v0.31.1 // indirect
-       github.com/prometheus/procfs v0.7.3 // indirect
        github.com/rs/zerolog v1.25.0
        github.com/sergi/go-diff v1.2.0 // indirect
        github.com/spf13/cobra v1.2.1
        github.com/xanzy/ssh-agent v0.3.1 // indirect
-       golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
-       golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect
-       golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 // indirect
+       github.com/yuin/gopher-lua v1.0.0 // indirect
        golang.org/x/text v0.3.7 // indirect
        google.golang.org/genproto v0.0.0-20211016002631-37fc39342514 // indirect
        google.golang.org/grpc v1.41.0
diff --git a/go.sum b/go.sum
index 4bcbba315d276f08f2b9c9834be72994718ba83a..d968c1ad40686289439c61b67553f9e1bc54f43f 100644 (file)
--- a/go.sum
+++ b/go.sum
@@ -48,6 +48,9 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
+github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
+github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
+github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0=
 github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84=
@@ -67,6 +70,12 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
+github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
+github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
+github.com/alicebob/miniredis v2.5.0+incompatible h1:yBHoLpsyjupjz3NL3MhKMVkR41j82Yjf3KFv7ApYzUI=
+github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk=
+github.com/alicebob/miniredis/v2 v2.23.1 h1:jR6wZggBxwWygeXcdNyguCOCIjPsZyNUNlAkTx2fu0U=
+github.com/alicebob/miniredis/v2 v2.23.1/go.mod h1:84TWKZlxYkfgMucPBf5SOQBYJceZeQRFIaQgNMiCX6Q=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
 github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
@@ -75,6 +84,8 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM=
+github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@@ -100,6 +111,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5O
 github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
 github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
+github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
 github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
@@ -166,6 +179,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
 github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
@@ -206,6 +220,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
 github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
 github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
 github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
+github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
 github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
 github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -221,6 +237,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
 github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
@@ -257,14 +274,22 @@ github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPT
 github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
 github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
 github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
+github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
 github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
 github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
+github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw=
+github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
 github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
 github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
 github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
 github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-msgpack v1.1.5 h1:9byZdVjKTe5mce63pRVNP1L7UAmdHOTEMGehn6KvJWs=
+github.com/hashicorp/go-msgpack v1.1.5/go.mod h1:gWVc3sv/wbDmR3rQsj1CAktEZzoz1YNK9NfGLXJ69/4=
 github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
 github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
 github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI=
 github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
 github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
@@ -287,6 +312,8 @@ github.com/hashicorp/mdns v1.0.0 h1:WhIgCr5a7AaVH6jPUwjtRuuE7/RDufnUvzIr48smyxs=
 github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
 github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M=
 github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/raft v1.3.11 h1:p3v6gf6l3S797NnK5av3HcczOC1T5CLoaRvg0g9ys4A=
+github.com/hashicorp/raft v1.3.11/go.mod h1:J8naEwc6XaaCfts7+28whSeRvCqTd6e20BlCU3LtEO4=
 github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0=
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -321,6 +348,8 @@ github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHz
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
+github.com/klauspost/compress v1.15.11 h1:Lcadnb3RKGin4FYM/orgq0qde+nc15E5Cbqg4B9Sx9c=
+github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -336,14 +365,20 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
 github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
 github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A=
 github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA=
 github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
 github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
+github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
 github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
+github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
 github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
 github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
@@ -351,6 +386,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0j
 github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA=
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
+github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
 github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -375,12 +412,36 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nats-io/gnatsd v1.4.1 h1:RconcfDeWpKCD6QIIwiVFcvForlXpWeJP7i5/lDLy44=
+github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ=
+github.com/nats-io/jwt/v2 v2.3.0 h1:z2mA1a7tIf5ShggOFlR1oBPgd6hGqcDYsISxZByUzdI=
+github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k=
+github.com/nats-io/nats-server v1.4.1 h1:Ul1oSOGNV/L8kjr4v6l2f9Yet6WY+LevH1/7cRZ/qyA=
+github.com/nats-io/nats-server v1.4.1/go.mod h1:c8f/fHd2B6Hgms3LtCaI7y6pC4WD1f4SUxcCud5vhBc=
+github.com/nats-io/nats-server/v2 v2.9.3 h1:HrfzA7G9LNetKkm1z+jU/e9kuAe+E6uaBuuq9EB5sQQ=
+github.com/nats-io/nats-server/v2 v2.9.3/go.mod h1:4sq8wvrpbvSzL1n3ZfEYnH4qeUuIl5W990j3kw13rRk=
+github.com/nats-io/nats-server/v2 v2.9.10 h1:LMC46Oi9E6BUx/xBsaCVZgofliAqKQzRPU6eKWkN8jE=
+github.com/nats-io/nats-server/v2 v2.9.10/go.mod h1:AB6hAnGZDlYfqb7CTAm66ZKMZy9DpfierY1/PbpvI2g=
+github.com/nats-io/nats-streaming-server v0.25.2 h1:cWjytvYksYPgnXnSocqnRWVrSgLclusnPGBNHQR4SqI=
+github.com/nats-io/nats-streaming-server v0.25.2/go.mod h1:bRbgx+iCG6EZEXpqVMroRDuCGwR1iW+ta84aEGBaMhI=
+github.com/nats-io/nats.go v1.16.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
+github.com/nats-io/nats.go v1.17.0 h1:1jp5BThsdGlN91hW0k3YEfJbfACjiOYtUiLXG0RL4IE=
+github.com/nats-io/nats.go v1.17.0/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w=
+github.com/nats-io/nats.go v1.19.0 h1:H6j8aBnTQFoVrTGB6Xjd903UMdE7jz6DS4YkmAqgZ9Q=
+github.com/nats-io/nats.go v1.19.0/go.mod h1:tLqubohF7t4z3du1QDPYJIQQyhb4wl6DhjxEajSI7UA=
+github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8=
+github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4=
+github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
+github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/nats-io/stan.go v0.10.3 h1:8DOyQJ0+nza3zSVJZ19/cpikkrWA4rSKB3YvckIGOTI=
+github.com/nats-io/stan.go v0.10.3/go.mod h1:Cgf5zk6kKpOCqqUIJeuBz6ZDz9osT791VhS6m28sSQQ=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
 github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
 github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
 github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ=
 github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
 github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -393,7 +454,9 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
 github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
@@ -403,17 +466,21 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
 github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
 github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
 github.com/prometheus/common v0.31.1 h1:d18hG4PkHnNAKNMOmFuXFaiY8Us0nird/2m60uS1AMs=
 github.com/prometheus/common v0.31.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
 github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
 github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
+github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
 github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
 github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/rogpeppe/fastuuid v1.2.0 h1:Ppwyp6VYCF1nvBTXL3trRso7mXMlRrw9ooo375wvi2s=
@@ -469,8 +536,10 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
 github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0=
 github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo=
 github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w=
@@ -480,6 +549,11 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
+github.com/yuin/gopher-lua v1.0.0 h1:pQCf0LN67Kf7M5u7vRd40A8M1I8IMLrxlqngUJgZ0Ow=
+github.com/yuin/gopher-lua v1.0.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
+go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
+go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
 go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw=
 go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
 go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU=
@@ -498,6 +572,8 @@ go.opentelemetry.io/proto/otlp v0.7.0 h1:rwOQPCuKAKmwGKq2aVNnYIibI6wnV7EvzgfTCzc
 go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
 go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/automaxprocs v1.5.1 h1:e1YG66Lrk73dn4qhg8WFSvhF0JuFQF0ERIp4rpuV8Qk=
+go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66vU6XU=
 go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
@@ -511,11 +587,16 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
 golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2 h1:x8vtB3zMecnlqZIwJNUUpwYKYSqCz5jXbiyv0ZJJZeI=
+golang.org/x/crypto v0.0.0-20221010152910-d6f0a8c073c2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -598,6 +679,7 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY=
 golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -624,12 +706,16 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -641,6 +727,7 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -661,6 +748,7 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -682,6 +770,10 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211015200801-69063c4bb744 h1:KzbpndAYEM+4oHRp9JmB2ewj0NHHxO3Z0g7Gus2O1kk=
 golang.org/x/sys v0.0.0-20211015200801-69063c4bb744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20221010170243-090e33056c14 h1:k5II8e6QD8mITdi+okbbmR/cIyEbeXLBhy5Ha4nevyc=
+golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -698,6 +790,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
 golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
 golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
+golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -705,6 +799,7 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
 golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190424220101-1e8e1cfdf96b/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
index 1de768710df7425f8fbc25bd0f5cc181100cbcf9..3dafdacbc03c6b3c3f839cbdc0bcf128c1b717a5 100644 (file)
@@ -5,11 +5,11 @@ use shared::{
     log::{error, info},
 };
 use std::{future::Future, pin::Pin};
-use tokio::{signal::{unix::SignalKind}, sync::oneshot};
+use tokio::{signal::unix::SignalKind, sync::oneshot};
 
-pub type AnyhowResultFuture<T> = Pin<Box<dyn Future<Output = Result<T>>>>;
+pub type AnyhowResultFuture<T> = Pin<Box<dyn Future<Output = Result<T>> + Send>>;
 pub trait Component: Send + Sync + 'static + Sized {
-    type Config: Default + Clone + DeserializeOwned;
+    type Config: Default + Clone + DeserializeOwned + Send;
 
     const SERVICE_NAME: &'static str;
     fn start(
@@ -32,7 +32,11 @@ pub trait Component: Send + Sync + 'static + Sized {
             tokio::spawn(async move {});
 
             tokio::spawn(async move {
-                match tokio::signal::unix::signal(SignalKind::terminate()).unwrap().recv().await {
+                match tokio::signal::unix::signal(SignalKind::terminate())
+                    .unwrap()
+                    .recv()
+                    .await
+                {
                     Some(()) => {
                         info!("Stopping program.");
 
@@ -44,7 +48,6 @@ pub trait Component: Send + Sync + 'static + Sized {
                     }
                 }
             });
-
             self.start(settings?, stop_channel).await
         })
     }
@@ -55,8 +58,9 @@ macro_rules! ignite {
     ($c:ty) => {
         #[allow(dead_code)]
         fn main() -> anyhow::Result<()> {
+            use leash::Component;
             let rt = tokio::runtime::Runtime::new()?;
-            rt.block_on(Box::new(<$c as Component>::new())._internal_start())?;
+            rt.block_on(<$c as Component>::new()._internal_start())?;
             Ok(())
         }
     };
@@ -67,7 +71,7 @@ mod test {
     use serde::Deserialize;
     use tokio::sync::oneshot;
 
-    use crate::Component;
+    use crate as leash;
 
     #[derive(Clone, Copy)]
     struct TestComponent {}
@@ -75,7 +79,7 @@ mod test {
     #[derive(Default, Clone, Deserialize, Copy)]
     struct TestComponentConfig {}
 
-    impl Component for TestComponent {
+    impl leash::Component for TestComponent {
         type Config = TestComponentConfig;
         const SERVICE_NAME: &'static str = "test_component";
 
index dc922d5c01fa236917191ff9d0f1eee0e7170ead..3529c462e29a4b61d9f9b6542fa9fe2fce8f3a43 100644 (file)
@@ -19,7 +19,7 @@ pub struct NatsConfiguration {
     pub host: String,
 }
 
-impl From<NatsConfiguration> for Pin<Box<dyn Future<Output = anyhow::Result<Client>>>> {
+impl From<NatsConfiguration> for Pin<Box<dyn Future<Output = anyhow::Result<Client>> + Send>> {
     fn from(value: NatsConfiguration) -> Self {
         Box::pin(async move { Ok(async_nats::connect(value.host).await?) })
     }