fix: Import*Actor shutsdown properly on error
closes kemitix/trello-to-deck#6
This commit is contained in:
parent
6e7244e1e4
commit
9c52da41c0
4 changed files with 92 additions and 67 deletions
|
@ -1,15 +1,17 @@
|
||||||
use color_eyre::eyre::Context;
|
|
||||||
//
|
//
|
||||||
use crate::import::rate_limit::{RateLimitActor, RequestToken};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use color_eyre::eyre::Context;
|
||||||
|
use kameo::{actor::ActorRef, mailbox::unbounded::UnboundedMailbox, Actor};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ask, e, f,
|
ask, f,
|
||||||
nextcloud::model::{NextcloudBoardId, NextcloudCardId, NextcloudStackId},
|
import::rate_limit::{RateLimitActor, RequestToken},
|
||||||
|
nextcloud::model::{Attachment, NextcloudBoardId, NextcloudCardId, NextcloudStackId},
|
||||||
on_actor_start, p,
|
on_actor_start, p,
|
||||||
trello::model::{attachment::TrelloAttachment, card::TrelloCardId},
|
trello::model::{attachment::TrelloAttachment, card::TrelloCardId},
|
||||||
FullCtx,
|
FullCtx,
|
||||||
};
|
};
|
||||||
use kameo::actor::ActorRef;
|
|
||||||
use kameo::{mailbox::unbounded::UnboundedMailbox, Actor};
|
|
||||||
|
|
||||||
pub(crate) struct ImportAttachmentActor {
|
pub(crate) struct ImportAttachmentActor {
|
||||||
ctx: FullCtx,
|
ctx: FullCtx,
|
||||||
|
@ -40,6 +42,39 @@ impl ImportAttachmentActor {
|
||||||
rate_limit_actor,
|
rate_limit_actor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn import_attachment(&self, file_name: &Path) -> color_eyre::Result<Attachment> {
|
||||||
|
let temp_fs = kxio::fs::temp()?;
|
||||||
|
let file_path = temp_fs.base().join(file_name);
|
||||||
|
|
||||||
|
// - - - download the attachment from trello
|
||||||
|
ask!(self.rate_limit_actor, RequestToken)?;
|
||||||
|
let attachment_path = self
|
||||||
|
.ctx
|
||||||
|
.trello_client()
|
||||||
|
.save_attachment(
|
||||||
|
&self.trello_card_id,
|
||||||
|
&self.trello_attachment.id,
|
||||||
|
Some(&file_path),
|
||||||
|
&temp_fs,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.with_context(|| f!("saving attachment {}", file_path.display()))?;
|
||||||
|
|
||||||
|
// - - - upload the attachment to nextcloud card
|
||||||
|
tracing::info!("Nextcloud: upload attachment");
|
||||||
|
self.ctx
|
||||||
|
.deck_client()
|
||||||
|
.add_attachment_to_card(
|
||||||
|
self.nextcloud_board_id,
|
||||||
|
self.nextcloud_stack_id,
|
||||||
|
self.nextcloud_card_id,
|
||||||
|
&temp_fs.file(&attachment_path),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.result
|
||||||
|
.with_context(|| f!("adding attachment to card {}", file_path.display()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl Actor for ImportAttachmentActor {
|
impl Actor for ImportAttachmentActor {
|
||||||
type Mailbox = UnboundedMailbox<Self>;
|
type Mailbox = UnboundedMailbox<Self>;
|
||||||
|
@ -50,61 +85,28 @@ impl Actor for ImportAttachmentActor {
|
||||||
">> Adding attachment: {}",
|
">> Adding attachment: {}",
|
||||||
this.trello_attachment.name
|
this.trello_attachment.name
|
||||||
);
|
);
|
||||||
// - - - download the attachment from trello
|
|
||||||
let file_name = f!(
|
let file_name = f!(
|
||||||
"{}-{}",
|
"{}-{}",
|
||||||
this.trello_attachment.id,
|
this.trello_attachment.id,
|
||||||
this.trello_attachment.name
|
this.trello_attachment.name
|
||||||
);
|
);
|
||||||
let file_path = this.ctx.temp_fs.base().join(&file_name);
|
|
||||||
ask!(this.rate_limit_actor, RequestToken)?; // FIXME: (#6) handle error
|
|
||||||
let attachment_path = this
|
|
||||||
.ctx
|
|
||||||
.trello_client()
|
|
||||||
.save_attachment(
|
|
||||||
&this.trello_card_id,
|
|
||||||
&this.trello_attachment.id,
|
|
||||||
Some(&file_path),
|
|
||||||
&this.ctx.temp_fs,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.with_context(|| f!("saving attachment {}", file_path.display()))?; // FIXME: (#6) handle error
|
|
||||||
let attachment_file = this.ctx.temp_fs.file(&attachment_path);
|
|
||||||
// - - - upload the attachment to nextcloud card
|
|
||||||
tracing::info!("Nextcloud: upload attachment");
|
|
||||||
let attachment = this
|
|
||||||
.ctx
|
|
||||||
.deck_client()
|
|
||||||
.add_attachment_to_card(
|
|
||||||
this.nextcloud_board_id,
|
|
||||||
this.nextcloud_stack_id,
|
|
||||||
this.nextcloud_card_id,
|
|
||||||
&attachment_file,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.result
|
|
||||||
.inspect_err(|e| {
|
|
||||||
e!(
|
|
||||||
this.ctx.prt,
|
|
||||||
">> Error adding attachment {} to card: {}",
|
|
||||||
file_path.display(),
|
|
||||||
e.to_string()
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.with_context(|| f!("adding attachment to card {}", file_path.display()))?; // FIXME: (#6) handle error
|
|
||||||
p!(
|
|
||||||
this.ctx.prt,
|
|
||||||
">> Attachment added: {}:{}",
|
|
||||||
attachment.id,
|
|
||||||
attachment.attachment_type,
|
|
||||||
// attachment.extended_data.mimetype
|
|
||||||
);
|
|
||||||
// delete local copy of attachment
|
|
||||||
attachment_file
|
|
||||||
.remove()
|
|
||||||
.with_context(|| f!("deleting temp file {attachment_file}"))?; // FIXME: (#6) handle error
|
|
||||||
|
|
||||||
tracing::info!("ImportAttachmentActor finished");
|
match this.import_attachment(&PathBuf::from(file_name)).await {
|
||||||
|
Ok(attachment) => {
|
||||||
|
p!(
|
||||||
|
this.ctx.prt,
|
||||||
|
">> Attachment added: {}:{}",
|
||||||
|
attachment.id,
|
||||||
|
attachment.attachment_type,
|
||||||
|
// attachment.extended_data.mimetype
|
||||||
|
);
|
||||||
|
tracing::info!("ImportAttachmentActor finished");
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!(?err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(actor_ref.stop_gracefully().await?)
|
Ok(actor_ref.stop_gracefully().await?)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,8 +73,9 @@ impl Actor for ImportCardActor {
|
||||||
0 => None,
|
0 => None,
|
||||||
_ => Some(NextcloudCardDescription::from(&this.trello_card.desc)),
|
_ => Some(NextcloudCardDescription::from(&this.trello_card.desc)),
|
||||||
};
|
};
|
||||||
|
|
||||||
tracing::info!("Nextcloud: Create card");
|
tracing::info!("Nextcloud: Create card");
|
||||||
let nextcloud_card = this
|
let nextcloud_card_id = match this
|
||||||
.ctx
|
.ctx
|
||||||
.deck_client()
|
.deck_client()
|
||||||
.create_card(
|
.create_card(
|
||||||
|
@ -84,7 +85,14 @@ impl Actor for ImportCardActor {
|
||||||
desc.as_ref(),
|
desc.as_ref(),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.result?; // FIXME: (#6) handle error
|
.result
|
||||||
|
{
|
||||||
|
Ok(card) => card.id,
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!(?err);
|
||||||
|
return Ok(actor_ref.stop_gracefully().await?);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut limit = RateLimit::new("labels & attachments", 10, 10.0, this.ctx.now());
|
let mut limit = RateLimit::new("labels & attachments", 10, 10.0, this.ctx.now());
|
||||||
|
|
||||||
|
@ -101,7 +109,7 @@ impl Actor for ImportCardActor {
|
||||||
this.ctx.clone(),
|
this.ctx.clone(),
|
||||||
this.nextcloud_board_id,
|
this.nextcloud_board_id,
|
||||||
this.nextcloud_stack_id,
|
this.nextcloud_stack_id,
|
||||||
nextcloud_card.id,
|
nextcloud_card_id,
|
||||||
trello_label,
|
trello_label,
|
||||||
this.labels_actor_ref.clone(),
|
this.labels_actor_ref.clone(),
|
||||||
)
|
)
|
||||||
|
@ -129,7 +137,7 @@ impl Actor for ImportCardActor {
|
||||||
this.ctx.clone(),
|
this.ctx.clone(),
|
||||||
this.nextcloud_board_id,
|
this.nextcloud_board_id,
|
||||||
this.nextcloud_stack_id,
|
this.nextcloud_stack_id,
|
||||||
nextcloud_card.id,
|
nextcloud_card_id,
|
||||||
this.trello_card.id.clone(),
|
this.trello_card.id.clone(),
|
||||||
trello_attachment,
|
trello_attachment,
|
||||||
this.rate_limit_actor.clone(),
|
this.rate_limit_actor.clone(),
|
||||||
|
|
|
@ -41,17 +41,24 @@ impl Actor for ImportLabelActor {
|
||||||
type Mailbox = UnboundedMailbox<Self>;
|
type Mailbox = UnboundedMailbox<Self>;
|
||||||
|
|
||||||
on_actor_start!(this, actor_ref, {
|
on_actor_start!(this, actor_ref, {
|
||||||
let label_id = ask!(
|
let label_id = match ask!(
|
||||||
this.labels_actor_ref,
|
this.labels_actor_ref,
|
||||||
labels::LookupNextcloudLabelId {
|
labels::LookupNextcloudLabelId {
|
||||||
trello_name: this.trello_label.name.clone(),
|
trello_name: this.trello_label.name.clone(),
|
||||||
trello_color: this.trello_label.color.clone()
|
trello_color: this.trello_label.color.clone()
|
||||||
}
|
}
|
||||||
)?; // FIXME: (#6) handle error
|
) {
|
||||||
|
Ok(label_id) => label_id,
|
||||||
|
Err(err) => {
|
||||||
|
tracing::error!(?err);
|
||||||
|
return Ok(actor_ref.stop_gracefully().await?);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// - - - add the label to the nextcloud card
|
// - - - add the label to the nextcloud card
|
||||||
tracing::info!("Nextcloud: add label to card");
|
tracing::info!("Nextcloud: add label to card");
|
||||||
this.ctx
|
match this
|
||||||
|
.ctx
|
||||||
.deck_client()
|
.deck_client()
|
||||||
.add_label_to_card(
|
.add_label_to_card(
|
||||||
this.nextcloud_board_id,
|
this.nextcloud_board_id,
|
||||||
|
@ -60,9 +67,11 @@ impl Actor for ImportLabelActor {
|
||||||
label_id,
|
label_id,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.result?; // FIXME: (#6) handle error
|
.result
|
||||||
|
{
|
||||||
tracing::info!("ImportLabelActor finished");
|
Ok(_) => tracing::info!("ImportLabelActor finished"),
|
||||||
|
Err(err) => tracing::error!(?err),
|
||||||
|
}
|
||||||
Ok(actor_ref.stop_gracefully().await?)
|
Ok(actor_ref.stop_gracefully().await?)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,7 +62,10 @@ impl Actor for ImportStackActor {
|
||||||
|
|
||||||
crate::p!(this.ctx.prt, "Importing stack: {}", this.trello_stack.name);
|
crate::p!(this.ctx.prt, "Importing stack: {}", this.trello_stack.name);
|
||||||
// - get the list of trello cards in the stack
|
// - get the list of trello cards in the stack
|
||||||
ask!(this.rate_limit_actor, RequestToken)?; // FIXME: (#6) handle error
|
if let Err(err) = ask!(this.rate_limit_actor, RequestToken) {
|
||||||
|
tracing::error!(?err);
|
||||||
|
return Ok(actor_ref.stop_gracefully().await?);
|
||||||
|
}
|
||||||
let mut trello_cards = trello_client
|
let mut trello_cards = trello_client
|
||||||
.list_cards(&TrelloListId::new(this.trello_stack.id.as_ref()))
|
.list_cards(&TrelloListId::new(this.trello_stack.id.as_ref()))
|
||||||
.await
|
.await
|
||||||
|
@ -75,7 +78,10 @@ impl Actor for ImportStackActor {
|
||||||
// - for each card in the trello stack
|
// - for each card in the trello stack
|
||||||
for trello_card in trello_cards.into_iter() {
|
for trello_card in trello_cards.into_iter() {
|
||||||
limit.block_until_token_available(this.ctx.now()).await;
|
limit.block_until_token_available(this.ctx.now()).await;
|
||||||
ask!(this.rate_limit_actor, RequestToken)?; // FIXME: (#6) handle error
|
if let Err(err) = ask!(this.rate_limit_actor, RequestToken) {
|
||||||
|
tracing::error!(?err);
|
||||||
|
return Ok(actor_ref.stop_gracefully().await?);
|
||||||
|
}
|
||||||
let trello_card_name = trello_card.name.clone();
|
let trello_card_name = trello_card.name.clone();
|
||||||
let child: ActorRef<ImportCardActor> = spawn_in_thread!(
|
let child: ActorRef<ImportCardActor> = spawn_in_thread!(
|
||||||
actor_ref.clone(),
|
actor_ref.clone(),
|
||||||
|
|
Loading…
Reference in a new issue