-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: data letter queue #73
Changes from 12 commits
d507793
ed8d3df
8db6859
3eb4433
7ebc833
d44bae6
5b0f1b3
b5ebc5f
eb5dcfe
98b6092
789353b
08d2215
a9b18c6
f563414
1de1c1c
8733c24
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -127,6 +127,8 @@ impl TestConfigBuilder { | |
self.storage.unwrap(), | ||
); | ||
|
||
drop_database().await.unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would need more explanation here. But if your question is any of these :
Then :
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yea the question was more, why do we drop in the middle of the code There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this is an initiation function for all the clients, which runs before each test we can drop the database at any point in this code. |
||
|
||
config_force_init(config).await; | ||
|
||
server | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,12 @@ | ||
use rstest::rstest; | ||
|
||
use crate::config::config; | ||
use crate::jobs::handle_job_failure; | ||
use crate::jobs::types::JobType; | ||
use crate::{jobs::types::JobStatus, tests::config::TestConfigBuilder}; | ||
|
||
use super::database::build_job_item; | ||
|
||
#[cfg(test)] | ||
pub mod da_job; | ||
|
||
|
@@ -15,18 +24,15 @@ use std::time::Duration; | |
use mockall::predicate::eq; | ||
use mongodb::bson::doc; | ||
use omniqueue::QueueError; | ||
use rstest::rstest; | ||
use tokio::time::sleep; | ||
use uuid::Uuid; | ||
|
||
use crate::config::config; | ||
use crate::jobs::constants::{JOB_PROCESS_ATTEMPT_METADATA_KEY, JOB_VERIFICATION_ATTEMPT_METADATA_KEY}; | ||
use crate::jobs::job_handler_factory::mock_factory; | ||
use crate::jobs::types::{ExternalId, JobItem, JobStatus, JobType, JobVerificationStatus}; | ||
use crate::jobs::types::{ExternalId, JobItem, JobVerificationStatus}; | ||
use crate::jobs::{create_job, increment_key_in_metadata, process_job, verify_job, Job, MockJob}; | ||
use crate::queue::job_queue::{JOB_PROCESSING_QUEUE, JOB_VERIFICATION_QUEUE}; | ||
use crate::tests::common::MessagePayloadType; | ||
use crate::tests::config::TestConfigBuilder; | ||
|
||
/// Tests `create_job` function when job is not existing in the db. | ||
#[rstest] | ||
|
@@ -501,3 +507,90 @@ fn build_job_item_by_type_and_status(job_type: JobType, job_status: JobStatus, i | |
version: 0, | ||
} | ||
} | ||
|
||
#[rstest] | ||
#[case(JobType::SnosRun, JobStatus::Failed)] | ||
#[tokio::test] | ||
async fn handle_job_failure_with_failed_job_status_works(#[case] job_type: JobType, #[case] job_status: JobStatus) { | ||
TestConfigBuilder::new().build().await; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. move this to a fixture There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned in here.
We can make fixture for tests under same scope if they require same customised external clients. for eg : We can create a separate issue for this and resolve there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sounds good to me |
||
let config = config().await; | ||
let database_client = config.database(); | ||
let internal_id = 1; | ||
|
||
// create a job, with already available "last_job_status" | ||
let mut job_expected = build_job_item(job_type.clone(), job_status.clone(), internal_id); | ||
let mut job_metadata = job_expected.metadata.clone(); | ||
job_metadata.insert("last_job_status".to_string(), JobStatus::PendingVerification.to_string()); | ||
job_expected.metadata = job_metadata.clone(); | ||
|
||
let job_id = job_expected.id; | ||
|
||
// feeding the job to DB | ||
database_client.create_job(job_expected.clone()).await.unwrap(); | ||
|
||
// calling handle_job_failure | ||
handle_job_failure(job_id).await.expect("handle_job_failure failed to run"); | ||
|
||
let job_fetched = config.database().get_job_by_id(job_id).await.expect("Unable to fetch Job Data").unwrap(); | ||
|
||
assert_eq!(job_fetched, job_expected); | ||
} | ||
|
||
#[rstest] | ||
#[case::pending_verification(JobType::SnosRun, JobStatus::PendingVerification)] | ||
#[case::verification_timeout(JobType::SnosRun, JobStatus::VerificationTimeout)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are the other statuses not covered ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We initially covered all the statuses as shown here, but it felt redundant to test all, hence they were removed. What do you suggest @EvolveArt ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. well even if it feels redundant I think it's important to have them, you want to avoid having jobs at an unexpected state in the DLQ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Valid, Implemented |
||
#[tokio::test] | ||
async fn handle_job_failure_with_correct_job_status_works(#[case] job_type: JobType, #[case] job_status: JobStatus) { | ||
TestConfigBuilder::new().build().await; | ||
let config = config().await; | ||
let database_client = config.database(); | ||
let internal_id = 1; | ||
|
||
// create a job | ||
let job = build_job_item(job_type.clone(), job_status.clone(), internal_id); | ||
let job_id = job.id; | ||
|
||
// feeding the job to DB | ||
database_client.create_job(job.clone()).await.unwrap(); | ||
|
||
// calling handle_job_failure | ||
handle_job_failure(job_id).await.expect("handle_job_failure failed to run"); | ||
|
||
let job_fetched = config.database().get_job_by_id(job_id).await.expect("Unable to fetch Job Data").unwrap(); | ||
|
||
// creating expected output | ||
let mut job_expected = job.clone(); | ||
let mut job_metadata = job_expected.metadata.clone(); | ||
job_metadata.insert("last_job_status".to_string(), job_status.to_string()); | ||
job_expected.metadata = job_metadata.clone(); | ||
job_expected.status = JobStatus::Failed; | ||
|
||
assert_eq!(job_fetched, job_expected); | ||
} | ||
|
||
#[rstest] | ||
#[case(JobType::DataSubmission)] | ||
#[tokio::test] | ||
async fn handle_job_failure_job_status_completed_works(#[case] job_type: JobType) { | ||
let job_status = JobStatus::Completed; | ||
|
||
TestConfigBuilder::new().build().await; | ||
let config = config().await; | ||
let database_client = config.database(); | ||
let internal_id = 1; | ||
|
||
// create a job | ||
let job_expected = build_job_item(job_type.clone(), job_status.clone(), internal_id); | ||
let job_id = job_expected.id; | ||
|
||
// feeding the job to DB | ||
database_client.create_job(job_expected.clone()).await.unwrap(); | ||
|
||
// calling handle_job_failure | ||
handle_job_failure(job_id).await.expect("Test call to handle_job_failure should have passed."); | ||
|
||
// The completed job status on db is untouched. | ||
let job_fetched = config.database().get_job_by_id(job_id).await.expect("Unable to fetch Job Data").unwrap(); | ||
|
||
assert_eq!(job_fetched, job_expected); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we fail silently here ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DL-queue is supposed to handle actual failed cases.
If
JobStatus::Completed
job is pushed to DL-queue multiple times by the queuing agent,we prefer not stopping the orchestrator rather
failing silently
.