Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 1 addition & 3 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -374,9 +374,7 @@ impl Engine {
};
let res = xs::nu::add_core_commands(&mut xe, store)
.and_then(|()| xs::nu::add_read_commands(&mut xe, store, xs::nu::ReadMode::Stream))
.and_then(|()| {
xs::nu::add_write_commands(&mut xe, store, xs::nu::AppendMode::Direct)
});
.and_then(|()| xs::nu::add_write_commands(&mut xe, store, xs::nu::AppendMode::Direct));
self.state = xe.state;
res.map_err(|e| Error::from(e.to_string()))
}
Expand Down
8 changes: 6 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {

// Create cross.stream store if --store is specified
#[cfg(feature = "cross-stream")]
let store = match args.store {
let mut store = match args.store {
Some(ref path) => {
match Store::init(path.clone(), args.services, args.expose.clone()).await {
Ok(store) => Some(store),
Expand All @@ -673,7 +673,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
None => None,
};
#[cfg(not(feature = "cross-stream"))]
let store: Option<Store> = None;
let mut store: Option<Store> = None;

// Build $HTTP_NU options from CLI args
let http_nu_options = HttpNuOptions {
Expand Down Expand Up @@ -794,6 +794,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
)
.await?;

if let Some(store) = &mut store {
store.shutdown().await;
}

shutdown();
log_handle.join().ok();
Ok(())
Expand Down
48 changes: 44 additions & 4 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use tokio::sync::mpsc;
pub struct Store {
inner: xs::store::Store,
path: std::path::PathBuf,
service_handle: Option<tokio::task::JoinHandle<()>>,
}

#[cfg(not(feature = "cross-stream"))]
Expand All @@ -21,7 +22,11 @@ pub struct Store {
impl Store {
/// Wrap an existing xs::store::Store (no API server or services).
pub fn from_inner(inner: xs::store::Store, path: std::path::PathBuf) -> Self {
Self { inner, path }
Self {
inner,
path,
service_handle: None,
}
}

/// Create the store and spawn the API server and optional services.
Expand All @@ -42,6 +47,7 @@ impl Store {
});

// Processors (actor, service, action) -- each gets its own subscription
let mut service_handle = None;
if services {
let s = inner.clone();
tokio::spawn(async move {
Expand All @@ -51,11 +57,11 @@ impl Store {
});

let s = inner.clone();
tokio::spawn(async move {
service_handle = Some(tokio::spawn(async move {
if let Err(e) = xs::processor::service::run(s).await {
eprintln!("Service processor error: {e}");
}
});
}));

let s = inner.clone();
tokio::spawn(async move {
Expand All @@ -65,7 +71,37 @@ impl Store {
});
}

Ok(Self { inner, path })
Ok(Self {
inner,
path,
service_handle,
})
}

/// Runs the xs.stopping shutdown protocol: appends the xs.stopping frame so
/// the service processor gracefully terminates any child processes it
/// spawned, then waits for it to finish. Bounded by a timeout so a stuck
/// processor can't hang server exit.
pub async fn shutdown(&mut self) {
let Some(handle) = self.service_handle.take() else {
return;
};

if let Err(e) = self
.inner
.append(xs::store::Frame::builder("xs.stopping").build())
{
eprintln!("Error appending xs.stopping frame: {e}");
handle.abort();
return;
}

if tokio::time::timeout(std::time::Duration::from_secs(3), handle)
.await
.is_err()
{
eprintln!("Service processor did not stop within timeout");
}
}

/// Add store commands (.cat, .append, .cas, .last, etc.) to the engine.
Expand Down Expand Up @@ -205,6 +241,10 @@ impl Store {
unreachable!("Store is never constructed without cross-stream feature")
}

pub async fn shutdown(&mut self) {
unreachable!("Store is never constructed without cross-stream feature")
}

pub async fn topic_source(
&self,
_topic: &str,
Expand Down
55 changes: 28 additions & 27 deletions tests/cert.pem
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
-----BEGIN CERTIFICATE-----
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
Mo93qreQyFlvUZEg1GfEExfAik54TQ0Q9PTT
-----END CERTIFICATE-----
155 changes: 78 additions & 77 deletions tests/combined.pem
Original file line number Diff line number Diff line change
@@ -1,81 +1,82 @@
-----BEGIN CERTIFICATE-----
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
Mo93qreQyFlvUZEg1GfEExfAik54TQ0Q9PTT
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
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
g2rP/enadpNRaJbg4Bove6NeVRdlZiE=
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
nLY/nmfPKFz4VOyCHJJjBby7oepQ
-----END PRIVATE KEY-----
23 changes: 23 additions & 0 deletions tests/gen-combined-cert.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Regenerates the self-signed TLS test fixtures in this directory:
# cert.pem, key.pem, and combined.pem (cert.pem + key.pem concatenated).
#
# Used by server_test.rs: combined.pem is passed to `http-nu --tls`, and
# cert.pem is used as the curl --cacert to trust it. Run this from the repo
# root whenever the cert expires (openssl x509 -in tests/cert.pem -noout
# -dates):
#
# ./tests/gen-combined-cert.sh

set -euo pipefail
cd "$(dirname "$0")"

openssl req -x509 -newkey rsa:4096 -sha256 -days 36500 -nodes \
-keyout key.pem -out cert.pem \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"

cat cert.pem key.pem > combined.pem

echo "Regenerated cert.pem, key.pem, combined.pem"
openssl x509 -in cert.pem -noout -dates
Loading
Loading