Radish alpha
r
rad:zwTxygwuz5LDGBq255RA2CbNGrz8
Radicle CI broker
Radicle
Git
Handle errors by returning Err instead of panic
Merged liw opened 1 year ago
1 file changed +42 -14 a059a0fb bbaa1c27
modified src/db.rs
@@ -44,7 +44,8 @@ impl Db {
            conn: sqlite::open(filename).map_err(|e| DbError::open(filename, e))?,
        };

-
        let ms = MAX_WAIT.as_millis().try_into().unwrap();
+
        debug_assert!(MAX_WAIT.as_millis() < usize::MAX as u128); // safe conversion
+
        let ms = MAX_WAIT.as_millis() as usize;
        trace!("set busy timeout to {ms} milliseconds");
        db.conn
            .set_busy_timeout(ms)
@@ -116,8 +117,12 @@ impl Db {
    /// Create the counter with an initial value. Only use this if
    /// there isn't a counter row already.
    pub fn create_counter(&self, counter: i64) -> Result<(), DbError> {
-
        let mut insert = self.prepare("INSERT INTO counter_test (counter) VALUES (:1)")?;
-
        insert.stmt.bind((1, counter)).unwrap();
+
        let sql = "INSERT INTO counter_test (counter) VALUES (:1)";
+
        let mut insert = self.prepare(sql)?;
+
        insert
+
            .stmt
+
            .bind((1, counter))
+
            .map_err(|e| DbError::bind(sql, e))?;
        match insert.stmt.next() {
            Ok(_) => (),
            Err(e) => return Err(DbError::insert_counter(&insert.sql, e)),
@@ -127,8 +132,12 @@ impl Db {

    /// Update the counter to have a new value.
    pub fn update_counter(&self, counter: i64) -> Result<(), DbError> {
-
        let mut update = self.prepare("UPDATE counter_test SET counter = :1")?;
-
        update.stmt.bind((1, counter)).unwrap();
+
        let sql = "UPDATE counter_test SET counter = :1";
+
        let mut update = self.prepare(sql)?;
+
        update
+
            .stmt
+
            .bind((1, counter))
+
            .map_err(|e| DbError::bind(sql, e))?;
        match update.stmt.next() {
            Ok(_) => (),
            Err(e) => return Err(DbError::update_counter(&update.sql, e)),
@@ -138,13 +147,19 @@ impl Db {

    /// Return the current value of the counter, if any.
    pub fn get_counter(&self) -> Result<Option<i64>, DbError> {
-
        let mut select = self.prepare("SELECT counter FROM counter_test")?;
+
        let sql = "SELECT counter FROM counter_test";
+
        let mut select = self.prepare(sql)?;
        let mut counter = None;

        loop {
            match select.stmt.next() {
                Ok(State::Row) => {
-
                    counter = Some(select.stmt.read("counter").unwrap());
+
                    counter = Some(
+
                        select
+
                            .stmt
+
                            .read("counter")
+
                            .map_err(|e| DbError::read(sql, e))?,
+
                    );
                }
                Ok(State::Done) => {
                    break;
@@ -193,8 +208,8 @@ impl Db {
            .bind((":id", id.as_str()))
            .map_err(|e| DbError::bind(&select.sql, e))?;

-
        let mut timestamp = None;
-
        let mut event = None;
+
        let mut timestamp: Option<String> = None;
+
        let mut event: Option<BrokerEvent> = None;

        loop {
            match select.stmt.next() {
@@ -223,8 +238,8 @@ impl Db {
            }
        }

-
        if timestamp.is_some() && event.is_some() {
-
            let qe = QueuedEvent::new(id.clone(), timestamp.unwrap(), event.unwrap());
+
        if let (Some(ts), Some(ev)) = (timestamp, event) {
+
            let qe = QueuedEvent::new(id.clone(), ts, ev);
            Ok(Some(qe))
        } else {
            Ok(None)
@@ -347,7 +362,7 @@ impl Db {

        let mut run = None;

-
        select.stmt.reset().unwrap();
+
        select.stmt.reset().map_err(DbError::reset)?;
        loop {
            match select.stmt.next() {
                Ok(State::Row) => {
@@ -374,8 +389,7 @@ impl Db {

    /// Add a new CI run to the database, returning its id.
    pub fn push_run(&self, run: Run) -> Result<RunId, DbError> {
-
        assert!(run.adapter_run_id().is_some());
-
        let id = run.adapter_run_id().unwrap().clone();
+
        let id = run.adapter_run_id().ok_or(DbError::without_id())?.clone();

        let json = serde_json::to_string(&run).expect("serialize BrokerEvent to JSON");

@@ -520,6 +534,9 @@ pub enum DbError {
    #[error("failed to bind a value in SQL statement in SQLite: {0}")]
    Bind(String, #[source] sqlite::Error),

+
    #[error("failed to read a column value output of SQL statement in SQLite: {0}")]
+
    Read(String, #[source] sqlite::Error),
+

    #[error("failed to insert a counter into database")]
    InsertCounter(String, #[source] sqlite::Error),

@@ -559,6 +576,9 @@ pub enum DbError {
    #[error("failed to retrieve a CI run from database")]
    GetRun(String, #[source] sqlite::Error),

+
    #[error("programming error: pushed run does not have its run ID set")]
+
    WithoutId,
+

    #[error("failed to insert a CI run into database")]
    PushRun(String, #[source] sqlite::Error),

@@ -591,6 +611,10 @@ impl DbError {
        Self::Bind(sql.into(), e)
    }

+
    fn read(sql: &str, e: sqlite::Error) -> Self {
+
        Self::Read(sql.into(), e)
+
    }
+

    fn insert_counter(sql: &str, e: sqlite::Error) -> Self {
        Self::InsertCounter(sql.into(), e)
    }
@@ -639,6 +663,10 @@ impl DbError {
        Self::GetRun(sql.into(), e)
    }

+
    fn without_id() -> Self {
+
        Self::WithoutId
+
    }
+

    fn push_run(sql: &str, e: sqlite::Error) -> Self {
        Self::PushRun(sql.into(), e)
    }