#![allow(clippy::print_stdout)]
use cirrus::Cirrus;
use cirrus::auth::StaticTokenAuth;
use cirrus::{BulkIngestSpec, BulkJobState, BulkOperation};
use std::sync::Arc;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let auth = Arc::new(StaticTokenAuth::new(
std::env::var("SF_ACCESS_TOKEN")?,
std::env::var("SF_INSTANCE_URL")?,
));
let sf = Cirrus::builder().auth(auth).build()?;
let bulk = sf.bulk();
let ingest = bulk.ingest();
let spec = BulkIngestSpec {
object: "Account".into(),
operation: BulkOperation::Insert,
external_id_field_name: None,
line_ending: None,
column_delimiter: None,
assignment_rule_id: None,
};
let job = ingest.create(&spec).await?;
println!("created job: id={}, state={:?}", job.id, job.state);
let csv = "Name,Description\n\
cirrus-bulk-1,from bulk example\n\
cirrus-bulk-2,from bulk example\n\
cirrus-bulk-3,from bulk example\n";
ingest.upload(&job.id, bytes::Bytes::from(csv)).await?;
println!("uploaded {} bytes of CSV", csv.len());
ingest.close(&job.id).await?;
println!("closed job; polling for completion...");
let mut current = ingest.get(&job.id).await?;
for _ in 0..20 {
match current.state {
BulkJobState::JobComplete | BulkJobState::Failed | BulkJobState::Aborted => break,
_ => {
tokio::time::sleep(Duration::from_secs(2)).await;
current = ingest.get(&job.id).await?;
}
}
}
println!(
"final state: {:?}, processed={:?}, failed={:?}",
current.state, current.number_records_processed, current.number_records_failed,
);
Ok(())
}