• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tari-project / tari / 20715266036

05 Jan 2026 12:22PM UTC coverage: 59.702% (-0.9%) from 60.642%
20715266036

push

github

web-flow
chore(deps): bump azure/trusted-signing-action from 0.5.10 to 0.5.11 (#7632)

Bumps
[azure/trusted-signing-action](https://github.com/azure/trusted-signing-action)
from 0.5.10 to 0.5.11.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/azure/trusted-signing-action/releases">azure/trusted-signing-action's
releases</a>.</em></p>
<blockquote>
<h2>v0.5.11</h2>
<h2>What's Changed</h2>
<ul>
<li>fix: map to environment variables instead of directly from inputs by
<a href="https://github.com/Jaxelr"><code>@​Jaxelr</code></a> in <a
href="https://redirect.github.com/Azure/trusted-signing-action/pull/102">Azure/trusted-signing-action#102</a></li>
<li>chore: update codeowners to trusted signing team by <a
href="https://github.com/Jaxelr"><code>@​Jaxelr</code></a> in <a
href="https://redirect.github.com/Azure/trusted-signing-action/pull/103">Azure/trusted-signing-action#103</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Azure/trusted-signing-action/compare/v0...v0.5.11">https://github.com/Azure/trusted-signing-action/compare/v0...v0.5.11</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/Azure/trusted-signing-action/commit/1d365fec1"><code>1d365fe</code></a>
chore: update codeowners to trusted signing team (<a
href="https://redirect.github.com/azure/trusted-signing-action/issues/103">#103</a>)</li>
<li><a
href="https://github.com/Azure/trusted-signing-action/commit/34bc367eb"><code>34bc367</code></a>
fix: map to environment variables instead of directly from inputs (<a
href="https://redirect.github.com/azure/trusted-signing-action/issues/102">#102</a>)</li>
<li>See full diff in <a
href="https://github.com/azure/trusted-signing-action/compare/v0.5.10...v0.5.11">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubap... (continued)

69282 of 116047 relevant lines covered (59.7%)

300086.98 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.98
/common_sqlite/src/sqlite_connection_pool.rs
1
// Copyright 2020. The Tari Project
2
//
3
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
4
// following conditions are met:
5
//
6
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
7
// disclaimer.
8
//
9
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
10
// following disclaimer in the documentation and/or other materials provided with the distribution.
11
//
12
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
13
// products derived from this software without specific prior written permission.
14
//
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
16
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
21
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22

23
use core::time::Duration;
24
use std::{convert::TryFrom, fmt::Display, path::PathBuf};
25

26
use diesel::{
27
    r2d2::{ConnectionManager, Pool, PooledConnection},
28
    SqliteConnection,
29
};
30
use log::*;
31

32
use crate::{connection_options::ConnectionOptions, error::SqliteStorageError};
33

34
const LOG_TARGET: &str = "common_sqlite::sqlite_connection_pool";
35

36
/// The default timeout for acquiring an R2D2 pool connection over and above the PRAGMA busy timeout.
37
pub const R2D2_POOL_CONNECTION_DELTA: Duration = Duration::from_secs(5);
38
/// The default timeout for acquiring an R2D2 pool connection.
39
/// Note: The default R2D2 connection timeout is 30s.
40
pub const R2D2_POOL_CONNECTION_TIMEOUT: Duration = Duration::from_secs(30);
41

42
/// Thin wrapper around an r2d2 `Pool<SqliteConnection>` with standard SQLite
43
/// configuration (WAL, FKs, busy timeout) applied to each connection.
44
///
45
/// The pool is created lazily by calling [`create_pool`] once. After that,
46
/// callers can obtain connections via [`get_pooled_connection`], a timed
47
/// variant, or a non-blocking `try_get_pooled_connection`.
48
///
49
/// # Concurrency notes
50
/// SQLite allows only a single writer at a time (even in WAL mode). Keep write
51
/// transactions short and consider limiting concurrent writers at the
52
/// application layer (e.g. a semaphore) to reduce lock contention.
53
///
54
/// # Timeout interplay
55
/// The r2d2 **pool checkout** timeout is configured via
56
/// `Pool::builder().connection_timeout(...)` inside [`create_pool`]. This is
57
/// separate from SQLite’s `PRAGMA busy_timeout` set by [`ConnectionOptions`].
58
/// Prefer `connection_timeout >= busy_timeout` (plus a little headroom) to
59
/// avoid premature pool timeouts while connections are waiting on SQLite locks.
60
#[derive(Clone)]
61
pub struct SqliteConnectionPool {
62
    /// The underlying r2d2 pool. `None` until [`create_pool`] is called.
63
    pool: Option<Pool<ConnectionManager<SqliteConnection>>>,
64
    /// Database path / connection string (`:memory:`, filesystem path, or
65
    /// `file:NAME?mode=memory&cache=shared`).
66
    db_path: String,
67
    /// Maximum number of concurrently open connections managed by the pool.
68
    pool_size: usize,
69
    /// Per-connection SQLite options applied on acquisition.
70
    connection_options: ConnectionOptions,
71
}
72

73
impl SqliteConnectionPool {
74
    /// Create a wrapper with the given target database, pool size and
75
    /// connection options (WAL, FKs, busy timeout). The r2d2 pool is not built
76
    /// until [`create_pool`] is called.
77
    pub fn new(
330✔
78
        db_path: String,
330✔
79
        pool_size: usize,
330✔
80
        enable_wal: bool,
330✔
81
        enable_foreign_keys: bool,
330✔
82
        busy_timeout: Duration,
330✔
83
    ) -> Self {
330✔
84
        Self {
330✔
85
            pool: None,
330✔
86
            db_path,
330✔
87
            pool_size,
330✔
88
            connection_options: ConnectionOptions::new(enable_wal, enable_foreign_keys, busy_timeout),
330✔
89
        }
330✔
90
    }
330✔
91

92
    /// Create an sqlite connection pool managed by the pool connection manager
93
    pub fn create_pool(&mut self) -> Result<(), SqliteStorageError> {
330✔
94
        if self.pool.is_none() {
330✔
95
            let mut builder = Pool::builder()
330✔
96
                .max_size(u32::try_from(self.pool_size)?)
330✔
97
                .connection_customizer(Box::new(self.connection_options.clone()));
330✔
98
            if let Some(timeout) = self.connection_options.get_busy_timeout() {
330✔
99
                // When we get a pooled connection, we want the pool connection timeout to be longer
330✔
100
                // than the database busy timeout (set by `PRAGMA busy_timeout`). Here we set the
330✔
101
                // connection timeout to whatever the busy timeout is plus a delta (5s).
330✔
102
                builder = builder.connection_timeout(timeout + R2D2_POOL_CONNECTION_DELTA);
330✔
103
            } else {
330✔
104
                // If no busy timeout is set, we use the default value.
×
105
                builder = builder.connection_timeout(R2D2_POOL_CONNECTION_TIMEOUT);
×
106
            }
×
107
            let pool = builder
330✔
108
                .build(ConnectionManager::<SqliteConnection>::new(self.db_path.as_str()))
330✔
109
                .map_err(|e| SqliteStorageError::DieselR2d2Error(e.to_string()))?;
330✔
110
            self.pool = Some(pool);
330✔
111
        } else {
112
            warn!(target: LOG_TARGET, "Connection pool for {} already exists", self.db_path);
×
113
        }
114
        Ok(())
330✔
115
    }
330✔
116

117
    /// Return a pooled sqlite connection managed by the pool connection manager, waits for at most the configured
118
    /// connection timeout before returning an error.
119
    pub fn get_pooled_connection(
348,805✔
120
        &self,
348,805✔
121
    ) -> Result<PooledConnection<ConnectionManager<SqliteConnection>>, SqliteStorageError> {
348,805✔
122
        if let Some(pool) = self.pool.as_ref() {
348,805✔
123
            let start = std::time::Instant::now();
348,805✔
124
            let connection = pool.get().map_err(|e| {
348,805✔
125
                warn!(target: LOG_TARGET, "Connection pool state {:?}: {}", pool.state(), e);
×
126
                SqliteStorageError::DieselR2d2Error(e.to_string())
×
127
            });
×
128
            let timing = start.elapsed();
348,805✔
129
            if timing > Duration::from_millis(100) {
348,805✔
130
                debug!(target: LOG_TARGET, "Acquired 'get_pooled_connection' from pool in {:.2?}", timing);
469✔
131
            }
348,336✔
132
            connection
348,805✔
133
        } else {
134
            Err(SqliteStorageError::DieselR2d2Error("Pool does not exist".to_string()))
×
135
        }
136
    }
348,805✔
137

138
    /// Return a pooled sqlite connection managed by the pool connection manager, waits for at most supplied
139
    /// connection timeout before returning an error.
140
    pub fn get_pooled_connection_timeout(
×
141
        &self,
×
142
        timeout: Duration,
×
143
    ) -> Result<PooledConnection<ConnectionManager<SqliteConnection>>, SqliteStorageError> {
×
144
        if let Some(pool) = self.pool.clone() {
×
145
            let start = std::time::Instant::now();
×
146
            let connection = pool.get_timeout(timeout).map_err(|e| {
×
147
                warn!(target: LOG_TARGET, "Connection pool state {:?}: {}", pool.state(), e);
×
148
                SqliteStorageError::DieselR2d2Error(e.to_string())
×
149
            });
×
150
            let timing = start.elapsed();
×
151
            if timing > Duration::from_millis(100) {
×
152
                debug!(target: LOG_TARGET, "Acquired 'get_pooled_connection_timeout' from pool in {:.2?}", timing);
×
153
            }
×
154
            connection
×
155
        } else {
156
            Err(SqliteStorageError::DieselR2d2Error("Pool does not exist".to_string()))
×
157
        }
158
    }
×
159

160
    /// Return a pooled sqlite connection managed by the pool connection manager, returns None if there are no idle
161
    /// connections available in the pool. This method will not block waiting to establish a new connection.
162
    pub fn try_get_pooled_connection(
×
163
        &self,
×
164
    ) -> Result<Option<PooledConnection<ConnectionManager<SqliteConnection>>>, SqliteStorageError> {
×
165
        if let Some(pool) = self.pool.clone() {
×
166
            let start = std::time::Instant::now();
×
167
            let connection = pool.try_get();
×
168
            if connection.is_none() {
×
169
                warn!(target: LOG_TARGET, "No connections available, pool state {:?}", pool.state());
×
170
            } else {
171
                let timing = start.elapsed();
×
172
                if timing > Duration::from_millis(100) {
×
173
                    debug!(target: LOG_TARGET, "Acquired 'try_get_pooled_connection' from pool in {:.2?}", timing);
×
174
                }
×
175
            }
176
            Ok(connection)
×
177
        } else {
178
            Err(SqliteStorageError::DieselR2d2Error("Pool does not exist".to_string()))
×
179
        }
180
    }
×
181

182
    /// Returns the database path / connection string used by this pool.
183
    pub fn db_path(&self) -> PathBuf {
84,326✔
184
        PathBuf::from(&self.db_path)
84,326✔
185
    }
84,326✔
186

187
    /// Perform cleanup on the connection pool. This will drop the pool and return the state of the pool.
188
    pub fn cleanup(&mut self) -> Option<String> {
194✔
189
        if let Some(pool) = self.pool.take() {
194✔
190
            let state = format!("{:?}", pool.state());
194✔
191
            drop(pool);
194✔
192
            return Some(state);
194✔
193
        }
×
194
        None
×
195
    }
194✔
196
}
197

198
impl Display for SqliteConnectionPool {
199
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
×
200
        let pool_state = if let Some(pool) = self.pool.clone() {
×
201
            format!("{:?}", pool.state())
×
202
        } else {
203
            "None".to_string()
×
204
        };
205
        write!(
×
206
            f,
×
207
            "SqliteConnectionPool {{ pool state: {}, db_path: {}, pool_size: {}, connection_options: {:?} }}",
×
208
            pool_state, self.db_path, self.pool_size, self.connection_options
209
        )
210
    }
×
211
}
212

213
/// Helper trait for components that need a pooled SQLite connection.
214
pub trait PooledDbConnection: Send + Sync + Clone {
215
    /// Acquire a pooled connection, or return an error if the pool is
216
    /// unavailable or the checkout times out.
217
    type Error;
218

219
    fn get_pooled_connection(&self) -> Result<PooledConnection<ConnectionManager<SqliteConnection>>, Self::Error>;
220
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc