Fetch schedule message endpoint (#21)
textsender_api PR / Rustfmt (pull_request) Successful in 49s
textsender_api PR / Check (pull_request) Successful in 1m22s
textsender_api PR / Clippy (pull_request) Successful in 2m5s
Rust Build / Test Suite (pull_request) Successful in 35s
Rust Build / Rustfmt (pull_request) Successful in 41s
textsender_api PR / Rustfmt (pull_request) Successful in 49s
textsender_api PR / Check (pull_request) Successful in 1m22s
textsender_api PR / Clippy (pull_request) Successful in 2m5s
Rust Build / Test Suite (pull_request) Successful in 35s
Rust Build / Rustfmt (pull_request) Successful in 41s
Reviewed-on: phoenix/textsender_api#21
This commit was merged in pull request #21.
This commit is contained in:
Generated
+1
-1
@@ -2277,7 +2277,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textsender_api"
|
name = "textsender_api"
|
||||||
version = "0.1.14"
|
version = "0.1.15"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "textsender_api"
|
name = "textsender_api"
|
||||||
version = "0.1.14"
|
version = "0.1.15"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
rust-version = "1.96"
|
rust-version = "1.96"
|
||||||
|
|
||||||
|
|||||||
@@ -52,15 +52,10 @@ pub mod request {
|
|||||||
impl UpdateScheduledMessageStatusRequest {
|
impl UpdateScheduledMessageStatusRequest {
|
||||||
pub fn is_valid(&self) -> bool {
|
pub fn is_valid(&self) -> bool {
|
||||||
if !self.status.is_empty() || !self.scheduled_message_id.is_nil() {
|
if !self.status.is_empty() || !self.scheduled_message_id.is_nil() {
|
||||||
if self.status == textsender_models::message::scheduling::PENDING
|
self.status == textsender_models::message::scheduling::PENDING
|
||||||
|| self.status == textsender_models::message::scheduling::READY
|
|| self.status == textsender_models::message::scheduling::READY
|
||||||
|| self.status == textsender_models::message::scheduling::PROCESSING
|
|| self.status == textsender_models::message::scheduling::PROCESSING
|
||||||
|| self.status == textsender_models::message::scheduling::DONE
|
|| self.status == textsender_models::message::scheduling::DONE
|
||||||
{
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@@ -104,6 +99,8 @@ pub mod response {
|
|||||||
pub struct ChangedStatus {
|
pub struct ChangedStatus {
|
||||||
pub old_status: String,
|
pub old_status: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub use ScheduleMessageResponse as FetchScheduledMessageResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod endpoint {
|
pub mod endpoint {
|
||||||
@@ -243,6 +240,48 @@ pub mod endpoint {
|
|||||||
.is_some_and(|t| t - time::OffsetDateTime::now_utc() >= time::Duration::minutes(10))
|
.is_some_and(|t| t - time::OffsetDateTime::now_utc() >= time::Duration::minutes(10))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Endpoint to fetch Scheduled Message that is ready
|
||||||
|
#[utoipa::path(
|
||||||
|
get,
|
||||||
|
path = crate::caller::endpoints::FETCH_SCHEDULED_MESSAGE,
|
||||||
|
responses(
|
||||||
|
(status = 200, description = "Scheduled Message found", body = super::response::FetchScheduledMessageResponse),
|
||||||
|
(status = 400, description = "Error getting Scheduled Message", body = super::response::FetchScheduledMessageResponse)
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
pub async fn fetch_scheduled_message(
|
||||||
|
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||||
|
) -> (
|
||||||
|
axum::http::StatusCode,
|
||||||
|
axum::Json<super::response::FetchScheduledMessageResponse>,
|
||||||
|
) {
|
||||||
|
let mut response = super::response::FetchScheduledMessageResponse::default();
|
||||||
|
|
||||||
|
match scheduling_repo::fetch(&pool).await {
|
||||||
|
Ok(scheduled_message) => {
|
||||||
|
response.data.push(scheduled_message);
|
||||||
|
response.message = String::from(super::super::super::response::SUCCESSFUL);
|
||||||
|
|
||||||
|
(axum::http::StatusCode::OK, axum::Json(response))
|
||||||
|
}
|
||||||
|
Err(err) => match err {
|
||||||
|
sqlx::Error::RowNotFound => {
|
||||||
|
response.message = String::from("Nothing to fetch");
|
||||||
|
|
||||||
|
(axum::http::StatusCode::NO_CONTENT, axum::Json(response))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
eprintln!("Error: {err:?}");
|
||||||
|
response.message = String::from("Error");
|
||||||
|
(
|
||||||
|
axum::http::StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
axum::Json(response),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Endpoint to update status of Scheduled Message
|
/// Endpoint to update status of Scheduled Message
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
patch,
|
patch,
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ pub mod endpoints {
|
|||||||
pub const GET_SCHEDULED_MESSAGE_EVENT: &str = "/api/v1/schedule/message/event";
|
pub const GET_SCHEDULED_MESSAGE_EVENT: &str = "/api/v1/schedule/message/event";
|
||||||
/// Constant for deleting Scheduled Message Event endpoint
|
/// Constant for deleting Scheduled Message Event endpoint
|
||||||
pub const DELETE_SCHEDULED_MESSAGE_EVENT: &str = "/api/v1/schedule/message/event/{id}";
|
pub const DELETE_SCHEDULED_MESSAGE_EVENT: &str = "/api/v1/schedule/message/event/{id}";
|
||||||
|
/// Constant for fetching Scheduled Message endpoint
|
||||||
|
pub const FETCH_SCHEDULED_MESSAGE: &str = "/api/v1/schedule/message/fetch";
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod response {
|
pub mod response {
|
||||||
|
|||||||
@@ -160,6 +160,12 @@ pub mod init {
|
|||||||
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
|
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
crate::caller::endpoints::FETCH_SCHEDULED_MESSAGE,
|
||||||
|
get(scheduling_endpoints::fetch_scheduled_message).route_layer(
|
||||||
|
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
|
||||||
|
),
|
||||||
|
)
|
||||||
.layer(cors::configure_cors().await)
|
.layer(cors::configure_cors().await)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,36 @@ pub async fn get_with_user_id(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn fetch(
|
||||||
|
pool: &sqlx::PgPool,
|
||||||
|
) -> Result<textsender_models::message::scheduling::ScheduledMessage, sqlx::Error> {
|
||||||
|
match sqlx::query(
|
||||||
|
r#"
|
||||||
|
UPDATE "scheduled_messages"
|
||||||
|
SET status = $1
|
||||||
|
WHERE id = (
|
||||||
|
SELECT id FROM "scheduled_messages"
|
||||||
|
WHERE status = $2
|
||||||
|
ORDER BY id
|
||||||
|
FOR UPDATE SKIP LOCKED
|
||||||
|
LIMIT 1
|
||||||
|
)
|
||||||
|
RETURNING id, scheduled, created, status, user_id
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(textsender_models::message::scheduling::PROCESSING)
|
||||||
|
.bind(textsender_models::message::scheduling::READY)
|
||||||
|
.fetch_one(pool)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(row) => match parse_row(&row).await {
|
||||||
|
Ok(scheduled_message) => Ok(scheduled_message),
|
||||||
|
Err(err) => Err(err),
|
||||||
|
},
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_status(
|
pub async fn update_status(
|
||||||
pool: &sqlx::PgPool,
|
pool: &sqlx::PgPool,
|
||||||
id: &uuid::Uuid,
|
id: &uuid::Uuid,
|
||||||
|
|||||||
+126
@@ -377,6 +377,25 @@ mod request {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn fetch_scheduled_message(
|
||||||
|
app: &axum::Router,
|
||||||
|
) -> Result<axum::response::Response, axum::http::Error> {
|
||||||
|
match super::super::run_post(
|
||||||
|
None,
|
||||||
|
textsender_api::caller::endpoints::FETCH_SCHEDULED_MESSAGE,
|
||||||
|
axum::http::Method::GET,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(req) => match app.clone().oneshot(req).await {
|
||||||
|
Ok(response) => Ok(response),
|
||||||
|
Err(err) => Err(axum::http::Error::from(err)),
|
||||||
|
},
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_scheduled_message_status(
|
pub async fn update_scheduled_message_status(
|
||||||
app: &axum::Router,
|
app: &axum::Router,
|
||||||
id: &uuid::Uuid,
|
id: &uuid::Uuid,
|
||||||
@@ -1143,3 +1162,110 @@ async fn test_update_scheduled_message_status() {
|
|||||||
|
|
||||||
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
|
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_fetch_scheduled_message() {
|
||||||
|
let (tm_pool, db_name, pool) = db_mgr::get_database_ready().await;
|
||||||
|
let app = init::app(pool).await;
|
||||||
|
|
||||||
|
let mut contact_id: uuid::Uuid = uuid::Uuid::nil();
|
||||||
|
let mut message_id: uuid::Uuid = uuid::Uuid::nil();
|
||||||
|
let mut scheduled_message_id: uuid::Uuid = uuid::Uuid::nil();
|
||||||
|
|
||||||
|
match request::create_contact(&app).await {
|
||||||
|
Ok(response) => {
|
||||||
|
let resp = util::get_resp_data::<
|
||||||
|
textsender_api::caller::contact::response::AddContactResponse,
|
||||||
|
>(response)
|
||||||
|
.await;
|
||||||
|
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
|
||||||
|
contact_id = resp.data[0].id.unwrap();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
assert!(false, "Error: {:?}", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match request::message::create_message(&app).await {
|
||||||
|
Ok(response) => {
|
||||||
|
let resp = util::get_resp_data::<
|
||||||
|
textsender_api::caller::message::response::AddMessageResponse,
|
||||||
|
>(response)
|
||||||
|
.await;
|
||||||
|
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
|
||||||
|
let message = &resp.data[0];
|
||||||
|
message_id = message.id.unwrap();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
assert!(false, "Error: {:?}", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match request::message::scheduling::create_scheduled_message(&app).await {
|
||||||
|
Ok(response) => {
|
||||||
|
let resp = util::get_resp_data::<
|
||||||
|
textsender_api::caller::message::scheduling::response::ScheduleMessageResponse,
|
||||||
|
>(response)
|
||||||
|
.await;
|
||||||
|
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
|
||||||
|
scheduled_message_id = resp.data[0].id;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
assert!(false, "Error: {err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match request::message::scheduling::create_scheduled_message_event(
|
||||||
|
&app,
|
||||||
|
&contact_id,
|
||||||
|
&message_id,
|
||||||
|
&scheduled_message_id,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(response) => {
|
||||||
|
let resp = util::get_resp_data::<
|
||||||
|
textsender_api::caller::message::scheduling::response::CreateScheduleMessageEventResponse,
|
||||||
|
>(response)
|
||||||
|
.await;
|
||||||
|
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
assert!(false, "Error: {err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match request::message::scheduling::update_scheduled_message_status(
|
||||||
|
&app,
|
||||||
|
&scheduled_message_id,
|
||||||
|
textsender_models::message::scheduling::READY,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(response) => {
|
||||||
|
let resp = util::get_resp_data::<
|
||||||
|
textsender_api::caller::message::scheduling::response::UpdateScheduledMessageStatusResponse,
|
||||||
|
>(response)
|
||||||
|
.await;
|
||||||
|
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
assert!(false, "Error: {err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match request::message::scheduling::fetch_scheduled_message(&app).await {
|
||||||
|
Ok(response) => {
|
||||||
|
let resp = util::get_resp_data::<
|
||||||
|
textsender_api::caller::message::scheduling::response::FetchScheduledMessageResponse,
|
||||||
|
>(response)
|
||||||
|
.await;
|
||||||
|
assert_eq!(false, resp.data.is_empty(), "Should not be empty");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
assert!(false, "Error: {err:?}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = db_mgr::drop_database(&tm_pool, &db_name).await;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user