@@ -10,21 +10,16 @@ use std::fmt;
1010use std:: sync:: Arc ;
1111use tracing as log;
1212
13- #[ derive( Debug ) ]
14- pub enum HandlerError {
15- Message ( String ) ,
16- Other ( anyhow:: Error ) ,
17- }
18-
19- impl std:: error:: Error for HandlerError { }
20-
21- impl fmt:: Display for HandlerError {
22- fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
23- match self {
24- HandlerError :: Message ( msg) => write ! ( f, "{}" , msg) ,
25- HandlerError :: Other ( _) => write ! ( f, "An internal error occurred." ) ,
26- }
27- }
13+ /// Creates a [`UserError`] with message.
14+ ///
15+ /// Should be used when an handler is in error due to the user action's (not a PR,
16+ /// not a issue, not authorized, ...).
17+ ///
18+ /// Should be used like this `return user_error!("My error message.");`.
19+ macro_rules! user_error {
20+ ( $err: expr $( , ) ?) => {
21+ anyhow:: Result :: Err ( anyhow:: anyhow!( crate :: handlers:: UserError ( $err. into( ) ) ) )
22+ } ;
2823}
2924
3025mod assign;
@@ -61,6 +56,19 @@ mod shortcut;
6156mod transfer;
6257pub mod types_planning_updates;
6358
59+ pub struct Context {
60+ pub github : GithubClient ,
61+ pub zulip : ZulipClient ,
62+ pub team : TeamClient ,
63+ pub db : crate :: db:: ClientPool ,
64+ pub username : String ,
65+ pub octocrab : Octocrab ,
66+ /// Represents the workqueue (assigned open PRs) of individual reviewers.
67+ /// tokio's RwLock is used to avoid deadlocks, since we run on a single-threaded tokio runtime.
68+ pub workqueue : Arc < tokio:: sync:: RwLock < ReviewerWorkqueue > > ,
69+ pub gha_logs : Arc < tokio:: sync:: RwLock < GitHubActionLogsCache > > ,
70+ }
71+
6472pub async fn handle ( ctx : & Context , host : & str , event : & Event ) -> Vec < HandlerError > {
6573 let config = config:: get ( & ctx. github , event. repo ( ) ) . await ;
6674 if let Err ( e) = & config {
@@ -368,11 +376,15 @@ macro_rules! command_handlers {
368376 if let Some ( config) = & config. $name {
369377 $name:: handle_command( ctx, config, event, command)
370378 . await
371- . unwrap_or_else( |err| {
372- errors. push( HandlerError :: Other ( err. context( format!(
373- "error when processing {} command handler" ,
374- stringify!( $name)
375- ) ) ) )
379+ . unwrap_or_else( |mut err| {
380+ if let Some ( err) = err. downcast_mut:: <UserError >( ) {
381+ errors. push( HandlerError :: Message ( std:: mem:: take( & mut err. 0 ) ) ) ;
382+ } else {
383+ errors. push( HandlerError :: Other ( err. context( format!(
384+ "error when processing {} command handler" ,
385+ stringify!( $name)
386+ ) ) ) ) ;
387+ }
376388 } ) ;
377389 } else {
378390 errors. push( HandlerError :: Message ( format!(
@@ -416,15 +428,33 @@ command_handlers! {
416428 transfer: Transfer ,
417429}
418430
419- pub struct Context {
420- pub github : GithubClient ,
421- pub zulip : ZulipClient ,
422- pub team : TeamClient ,
423- pub db : crate :: db:: ClientPool ,
424- pub username : String ,
425- pub octocrab : Octocrab ,
426- /// Represents the workqueue (assigned open PRs) of individual reviewers.
427- /// tokio's RwLock is used to avoid deadlocks, since we run on a single-threaded tokio runtime.
428- pub workqueue : Arc < tokio:: sync:: RwLock < ReviewerWorkqueue > > ,
429- pub gha_logs : Arc < tokio:: sync:: RwLock < GitHubActionLogsCache > > ,
431+ #[ derive( Debug ) ]
432+ pub enum HandlerError {
433+ Message ( String ) ,
434+ Other ( anyhow:: Error ) ,
435+ }
436+
437+ impl std:: error:: Error for HandlerError { }
438+
439+ impl fmt:: Display for HandlerError {
440+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
441+ match self {
442+ HandlerError :: Message ( msg) => write ! ( f, "{}" , msg) ,
443+ HandlerError :: Other ( _) => write ! ( f, "An internal error occurred." ) ,
444+ }
445+ }
446+ }
447+
448+ /// Represent a user error.
449+ ///
450+ /// The message will be shown to the user via comment posted by this bot.
451+ #[ derive( Debug ) ]
452+ pub struct UserError ( String ) ;
453+
454+ impl std:: error:: Error for UserError { }
455+
456+ impl fmt:: Display for UserError {
457+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
458+ f. write_str ( & self . 0 )
459+ }
430460}
0 commit comments