Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
20 changes: 18 additions & 2 deletions src/infrastructure/http/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::{
sql::{DbError, SqlDb},
},
ln_verification,
shared::HomeserverObserver,
shared::HomeserverAdminAPI,
sms_verification::http::router,
};

Expand Down Expand Up @@ -54,7 +54,7 @@ impl HttpServer {
}

pub async fn start(config: EnvConfig) -> Result<Self, HttpServerError> {
HomeserverObserver::spawn_crash_on_unresponsive_homeserver(&config).await;
Self::err_on_homeserver_admin_api_failure(&config).await;

let db = SqlDb::connect(&config.database_url)
.await
Expand Down Expand Up @@ -105,6 +105,22 @@ impl HttpServer {
self.http_handle
.graceful_shutdown(Some(Duration::from_secs(5)));
}

// Verify homeserver is available at startup and credentials are correct, exit process if not.
async fn err_on_homeserver_admin_api_failure(config: &EnvConfig) {
let homeserver_admin_api = HomeserverAdminAPI::new(
&config.homeserver_admin_api_url,
&config.homeserver_admin_password,
&config.homeserver_pubky,
);
if let Err(e) = homeserver_admin_api.verify_password().await {
tracing::error!(
"Homeserver connection failed: {:?}. Stopping server because credentials are incorrect or homeserver is unavailable.",
e
);
std::process::exit(1);
}
}
}

impl Drop for HttpServer {
Expand Down
18 changes: 6 additions & 12 deletions src/ln_verification/app_state.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,22 @@
use crate::ln_verification::{
invoice_background_syncer::InvoiceBackgroundSyncer, service::LnVerificationService,
};
use std::sync::Arc;

use crate::ln_verification::service::LnVerificationService;
use crate::shared::HomeserverAdminAPI;

/// Application state for the Lightning Network verification HTTP handlers.
#[derive(Clone, Debug)]
pub struct AppState {
pub syncer: InvoiceBackgroundSyncer,
pub ln_service: LnVerificationService,
pub ln_service: Arc<LnVerificationService>,
pub homeserver_api: HomeserverAdminAPI,
}

impl AppState {
/// Create a new AppState instance.
///
/// Note: The caller is responsible for starting the background syncer
/// by calling `syncer.run()` in a spawned task.
pub fn new(
syncer: InvoiceBackgroundSyncer,
ln_service: LnVerificationService,
homeserver_api: HomeserverAdminAPI,
) -> Self {
/// by calling `ln_service.run_background_sync()` in a spawned task.
pub fn new(ln_service: Arc<LnVerificationService>, homeserver_api: HomeserverAdminAPI) -> Self {
Self {
syncer,
ln_service,
homeserver_api,
}
Expand Down
3 changes: 0 additions & 3 deletions src/ln_verification/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,4 @@ pub enum LnVerificationError {

#[error("Database error: {0}")]
Database(#[from] sqlx::Error),

#[error("Homeserver API error: {0}")]
Homeserver(reqwest::Error),
}
78 changes: 38 additions & 40 deletions src/ln_verification/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ use crate::{
EnvConfig,
infrastructure::http::HttpServerError,
ln_verification::{
VerificationId, app_state::AppState, error::LnVerificationError,
invoice_background_syncer::InvoiceBackgroundSyncer, phoenixd_api::PhoenixdAPI,
service::LnVerificationService,
VerificationId, app_state::AppState, error::LnVerificationError, phoenixd_api::PhoenixdAPI,
service::LnVerificationService, types::VerificationResponse,
},
shared::HomeserverAdminAPI,
};
Expand All @@ -30,25 +29,26 @@ pub async fn router(
&config.homeserver_admin_password,
&config.homeserver_pubky,
);

let ln_service = LnVerificationService::new(
db.clone(),
phoenixd_api.clone(),
phoenixd_api,
homeserver_api.clone(),
config.lightning_invoice_price_sat,
config.lightning_invoice_description.clone(),
config.lightning_invoice_expiry_seconds,
);
let ln_service = std::sync::Arc::new(ln_service);

let syncer = InvoiceBackgroundSyncer::new(ln_service.clone(), phoenixd_api).await;
let syncer_for_task = syncer.clone();
let service_for_task = ln_service.clone();
tokio::task::spawn(async move {
if let Err(e) = syncer_for_task.run().await {
if let Err(e) = service_for_task.run_background_sync().await {
tracing::error!(error = %e, "Error running invoice background syncer");
process::exit(1); // Force a restart of the server
}
});

let state = AppState::new(syncer, ln_service, homeserver_api);
let state = AppState::new(ln_service, homeserver_api);
Ok(Router::new()
.route("/", post(create_verification_handler))
.route("/{id}", get(get_verification_handler))
Expand Down Expand Up @@ -77,11 +77,14 @@ async fn get_verification_handler(
State(state): State<AppState>,
Path(id): Path<VerificationId>,
) -> Response {
let verification = match state.ln_service.get_verification(&id).await {
let verification = match state.ln_service.get_and_sync_verification(&id).await {
Ok(Some(verification)) => verification,
Ok(None) => return (StatusCode::NOT_FOUND, "Not found".to_string()).into_response(),
Ok(None) => {
return (StatusCode::NOT_FOUND, "Not found".to_string()).into_response();
}
Err(e) => return e.into_response(),
};

Json(GetVerificationResponse::from_entity(
verification,
state.homeserver_api.get_homeserver_pubky(),
Expand All @@ -94,36 +97,35 @@ async fn await_verification_handler(
State(state): State<AppState>,
Path(id): Path<VerificationId>,
) -> impl IntoResponse {
let mut verification = match state.ln_service.get_verification(&id).await {
Ok(Some(verification)) => verification,
Ok(None) => return (StatusCode::NOT_FOUND, "Not found".to_string()).into_response(),
let response = match state
.ln_service
.get_and_await_verification(&id, Duration::from_secs(60))
.await
{
Ok(Some(response)) => response,
Ok(None) => {
return (StatusCode::NOT_FOUND, "Not found".to_string()).into_response();
}
Err(e) => return e.into_response(),
};

if !verification.is_finalised() {
verification = match state
.syncer
.wait_for_payment(&id, Duration::from_secs(60))
.await
{
Ok(Some(verification)) => verification,
Ok(None) => {
return (
StatusCode::REQUEST_TIMEOUT,
"Long poll timeout. Please try again.".to_string(),
)
.into_response();
match response {
VerificationResponse::Success(verification) => {
if verification.is_finalised() {
tracing::info!("Awaited verification {}", verification.id);
}
Err(e) => return e.into_response(),
};
tracing::info!("Awaited verification {}", verification.id);
};

Json(GetVerificationResponse::from_entity(
verification,
state.homeserver_api.get_homeserver_pubky(),
))
.into_response()
Json(GetVerificationResponse::from_entity(
verification,
state.homeserver_api.get_homeserver_pubky(),
))
.into_response()
}
VerificationResponse::TimedOut => (
StatusCode::REQUEST_TIMEOUT,
"Long poll timeout. Please try again.".to_string(),
)
.into_response(),
}
}

/// Get the configured Lightning invoice price handler
Expand Down Expand Up @@ -185,10 +187,6 @@ impl IntoResponse for LnVerificationError {
tracing::error!(error = %err, "Phoenixd API error");
StatusCode::INTERNAL_SERVER_ERROR
}
LnVerificationError::Homeserver(ref err) => {
tracing::error!(error = %err, "Homeserver API error");
StatusCode::INTERNAL_SERVER_ERROR
}
LnVerificationError::Database(ref err) => {
tracing::error!(error = %err, "Database operation failed");
StatusCode::INTERNAL_SERVER_ERROR
Expand Down
132 changes: 0 additions & 132 deletions src/ln_verification/invoice_background_syncer.rs

This file was deleted.

2 changes: 1 addition & 1 deletion src/ln_verification/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
mod app_state;
mod error;
mod http;
mod invoice_background_syncer;
mod payment_hash;
mod phoenixd_api;
mod repository;
mod service;
mod types;
mod verification_id;
pub use http::router;
pub use repository::*;
Expand Down
Loading
Loading