Skip to content

Commit a0b1e77

Browse files
committed
fix: separate macros for tx and raw
1 parent 4fb85ec commit a0b1e77

7 files changed

Lines changed: 147 additions & 125 deletions

File tree

crates/service_utils/src/db.rs

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -8,58 +8,51 @@ pub mod utils;
88
pub type PgSchemaConnectionPool = Pool<ConnectionManager<PgConnection>>;
99

1010
/// Helper macro to run a database query with connection management and error handling.
11-
/// Supports both raw connection mode and transaction mode.
1211
/// Example usage:
1312
/// ```rust,ignore
14-
/// // Using raw connection mode
1513
/// run_query!(db_pool, conn, {
1614
/// // Your query logic here, using `conn` as the database connection
1715
/// });
18-
/// // Using transaction mode
19-
/// run_query!(db_pool, tx conn, {
20-
/// // Your query logic here, using `conn` as the database connection within a transaction
21-
/// });
2216
/// ```
2317
#[macro_export]
2418
macro_rules! run_query {
25-
// Public API — raw connection mode
26-
($db_pool:expr, $conn:ident, $body:expr) => {
27-
run_query!(@execute $db_pool, raw, $conn, $body)
28-
};
29-
30-
// Public API — transaction mode
31-
($db_pool:expr, tx $conn:ident, $body:expr) => {
32-
run_query!(@execute $db_pool, tx, $conn, $body)
33-
};
34-
35-
// Shared connection acquisition and execution logic
36-
(@execute $db_pool:expr, $mode:ident, $conn:ident, $body:expr) => {{
37-
match $db_pool.get() {
38-
Ok(mut $conn) => {
39-
diesel::Connection::set_prepared_statement_cache_size(
40-
&mut $conn,
41-
diesel::connection::CacheSize::Disabled,
42-
);
43-
44-
run_query!(@dispatch $mode, $conn, $body)
45-
}
46-
Err(e) => Err(
47-
superposition_macros::unexpected_error!(
48-
"Unable to get db connection from pool, error: {}", e
49-
),
50-
),
51-
}
19+
($db_pool:expr, $conn:ident, $body:expr) => {{
20+
let mut $conn = $db_pool.get().map_err(|e| {
21+
superposition_macros::unexpected_error!(
22+
"Unable to get db connection from pool, error: {}",
23+
e
24+
)
25+
})?;
26+
diesel::Connection::set_prepared_statement_cache_size(
27+
&mut $conn,
28+
diesel::connection::CacheSize::Disabled,
29+
);
30+
31+
$body
5232
}};
33+
}
5334

54-
// Dispatch logic based on execution mode
55-
(@dispatch raw, $conn:ident, $body:expr) => {{
56-
let $conn = &mut $conn;
57-
$body.map_err(Into::into)
35+
/// Helper macro to run a database query within a transaction, with connection management and error handling.
36+
/// Example usage:
37+
/// ```rust,ignore
38+
/// run_tx_query!(db_pool, |conn| {
39+
/// // Your transactional query logic here, using `conn` as the database connection
40+
/// });
41+
/// ```
42+
#[macro_export]
43+
macro_rules! run_tx_query {
44+
($db_pool:expr, $query_fn:expr) => {{
45+
let mut conn = $db_pool.get().map_err(|e| {
46+
superposition_macros::unexpected_error!(
47+
"Unable to get db connection from pool, error: {}",
48+
e
49+
)
50+
})?;
51+
diesel::Connection::set_prepared_statement_cache_size(
52+
&mut conn,
53+
diesel::connection::CacheSize::Disabled,
54+
);
55+
56+
diesel::Connection::transaction(&mut conn, $query_fn)
5857
}};
59-
60-
61-
// For transaction mode, we wrap the body in a transaction block
62-
(@dispatch tx, $conn:ident, $body:expr) => {
63-
diesel::Connection::transaction(&mut $conn, |$conn| $body).map_err(Into::into)
64-
};
6558
}

crates/service_utils/src/helpers.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,17 @@ pub fn get_workspace(
212212
workspace_schema_name: &SchemaName,
213213
db_pool: &PgSchemaConnectionPool,
214214
) -> result::Result<Workspace> {
215-
run_query!(
215+
let workspace = run_query!(
216216
db_pool,
217217
conn,
218218
workspaces::dsl::workspaces
219219
.filter(
220220
workspaces::workspace_schema_name.eq(workspace_schema_name.to_string()),
221221
)
222-
.get_result::<Workspace>(conn)
223-
)
222+
.get_result::<Workspace>(&mut conn)
223+
)?;
224+
225+
Ok(workspace)
224226
}
225227

226228
fn has_pattern_in_headers(headers: &CustomHeaders) -> (bool, bool) {

crates/superposition/src/organisation/handlers.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub async fn create_handler(
5959
let new_org = run_query!(state.db_pool, conn, {
6060
diesel::insert_into(organisations::table)
6161
.values(&new_org)
62-
.get_result(conn)
62+
.get_result(&mut conn)
6363
})?;
6464

6565
Ok(Json(new_org))
@@ -83,7 +83,7 @@ pub async fn update_handler(
8383
diesel::update(organisations::table)
8484
.filter(organisations::id.eq(org_id))
8585
.set((req, updated_at.eq(now), updated_by.eq(user.get_email())))
86-
.get_result(conn)
86+
.get_result(&mut conn)
8787
})?;
8888

8989
Ok(Json(updated_org))
@@ -95,11 +95,13 @@ pub async fn get_handler(
9595
org_id: Path<String>,
9696
state: Data<AppState>,
9797
) -> superposition::Result<Json<Organisation>> {
98-
let org = run_query!(state.db_pool, conn, {
98+
let org = run_query!(
99+
state.db_pool,
100+
conn,
99101
organisations::table
100102
.find(org_id.as_str())
101-
.first::<Organisation>(conn)
102-
})?;
103+
.first::<Organisation>(&mut conn)
104+
)?;
103105

104106
Ok(Json(org))
105107
}
@@ -111,11 +113,13 @@ pub async fn list_handler(
111113
filters: Query<PaginationParams>,
112114
) -> superposition::Result<Json<PaginatedResponse<Organisation>>> {
113115
if let Some(true) = filters.all {
114-
let result = run_query!(state.db_pool, conn, {
116+
let result = run_query!(
117+
state.db_pool,
118+
conn,
115119
organisations::table
116120
.order(organisations::created_at.desc())
117-
.get_results(conn)
118-
})?;
121+
.get_results(&mut conn)
122+
)?;
119123

120124
return Ok(Json(PaginatedResponse::all(result)));
121125
}
@@ -124,7 +128,7 @@ pub async fn list_handler(
124128
let total_items = run_query!(
125129
state.db_pool,
126130
conn,
127-
organisations::table.count().get_result(conn)
131+
organisations::table.count().get_result(&mut conn)
128132
)?;
129133

130134
// Set up pagination
@@ -141,7 +145,7 @@ pub async fn list_handler(
141145
}
142146

143147
// Get paginated results
144-
let data = run_query!(state.db_pool, conn, builder.load(conn))?;
148+
let data = run_query!(state.db_pool, conn, builder.load(&mut conn))?;
145149

146150
let total_pages = (total_items as f64 / limit as f64).ceil() as i64;
147151

crates/superposition/src/resolve/handlers.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,11 @@ async fn resolve_with_exp_handler(
4444
let query_filters = query_filters.into_inner();
4545
let identifier_query = identifier_query.into_inner();
4646
// TODO: Granularise the connection usage in this function once all crates are migrated
47-
let max_created_at = run_query!(state.db_pool, conn, {
48-
get_max_created_at(conn, &workspace_context.schema_name)
49-
})
47+
let max_created_at = run_query!(
48+
state.db_pool,
49+
conn,
50+
get_max_created_at(&mut conn, &workspace_context.schema_name)
51+
)
5052
.map_err(|e| log::error!("failed to fetch max timestamp from event_log : {e}"))
5153
.ok();
5254

@@ -64,49 +66,56 @@ async fn resolve_with_exp_handler(
6466
let config_ver = config_version.to_owned();
6567

6668
// TODO: Granularise the connection usage in this function once all crates are migrated
67-
let mut config = run_query!(state.db_pool, conn, {
69+
let mut config = run_query!(
70+
state.db_pool,
71+
conn,
6872
generate_config_from_version(
6973
&mut config_version,
70-
conn,
74+
&mut conn,
7175
&workspace_context.schema_name,
7276
)
73-
})?;
77+
)?;
7478

7579
if let (None, Some(identifier)) = (config_ver, identifier_query.identifier) {
7680
let context_map: &Map<String, Value> = &query_data;
7781
// TODO: Granularise the connection usage in this function once all crates are migrated
78-
let (applicable_variants, _) = run_query!(state.db_pool, conn, {
82+
let (applicable_variants, _) = run_query!(
83+
state.db_pool,
84+
conn,
7985
get_applicable_variants_helper(
80-
conn,
86+
&mut conn,
8187
context_map.clone(),
8288
&config.dimensions,
8389
identifier,
8490
&workspace_context,
8591
)
86-
})?;
92+
)?;
8793
query_data.insert("variantIds".to_string(), applicable_variants.into());
8894
}
8995

9096
// TODO: Granularise the connection usage in this function once all crates are migrated
91-
let resolved_config = run_query!(state.db_pool, conn, {
97+
let resolved_config = run_query!(
98+
state.db_pool,
99+
conn,
92100
resolve(
93101
&mut config,
94102
query_data,
95103
merge_strategy,
96-
conn,
104+
&mut conn,
97105
&query_filters,
98106
&workspace_context,
99107
&state.master_encryption_key,
100108
)
101-
})?;
109+
)?;
102110

103111
let mut resp = HttpResponse::Ok();
104112
add_last_modified_to_header(max_created_at, is_smithy, &mut resp);
105113
// TODO: Granularise the connection usage in this function once all crates are migrated
106-
run_query!(state.db_pool, conn, {
107-
add_audit_id_to_header(conn, &mut resp, &workspace_context.schema_name);
108-
Ok::<(), superposition::AppError>(())
109-
})?;
114+
run_query!(
115+
state.db_pool,
116+
conn,
117+
add_audit_id_to_header(&mut conn, &mut resp, &workspace_context.schema_name)
118+
);
110119
add_config_version_to_header(&config_version, &mut resp);
111120
Ok(resp.json(resolved_config))
112121
}

crates/superposition/src/webhooks/handlers.rs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ use chrono::Utc;
77
use context_aware_config::helpers::validate_change_reason;
88
use diesel::{ExpressionMethods, PgArrayExpressionMethods, QueryDsl, RunQueryDsl};
99
use service_utils::{
10-
run_query,
10+
run_query, run_tx_query,
1111
service::types::{AppState, WorkspaceContext},
1212
};
1313
use superposition_derives::authorized;
1414
use superposition_types::{
15-
PaginatedResponse, User,
15+
DBConnection, PaginatedResponse, User,
1616
api::webhook::{CreateWebhookRequest, UpdateWebhookRequest, WebhookName},
1717
custom_query::PaginationParams,
1818
database::{
@@ -48,7 +48,7 @@ async fn create_handler(
4848
validate_change_reason(
4949
&workspace_context,
5050
&req.change_reason,
51-
conn,
51+
&mut conn,
5252
&state.master_encryption_key,
5353
)
5454
)?;
@@ -84,7 +84,7 @@ async fn create_handler(
8484
diesel::insert_into(webhooks::table)
8585
.values(&webhook_data)
8686
.schema_name(&workspace_context.schema_name)
87-
.get_result::<Webhook>(conn)
87+
.get_result::<Webhook>(&mut conn)
8888
)?;
8989

9090
Ok(Json(created))
@@ -109,7 +109,7 @@ async fn update_handler(
109109
validate_change_reason(
110110
&workspace_context,
111111
&req.change_reason,
112-
conn,
112+
&mut conn,
113113
&state.master_encryption_key,
114114
)
115115
)?;
@@ -134,7 +134,7 @@ async fn update_handler(
134134
last_modified_by.eq(user.get_email()),
135135
))
136136
.schema_name(&workspace_context.schema_name)
137-
.get_result::<Webhook>(conn)
137+
.get_result::<Webhook>(&mut conn)
138138
)?;
139139

140140
Ok(Json(update))
@@ -163,11 +163,13 @@ async fn list_handler(
163163
pagination: Query<PaginationParams>,
164164
) -> superposition::Result<Json<PaginatedResponse<Webhook>>> {
165165
if let Some(true) = pagination.all {
166-
let result: Vec<Webhook> = run_query!(state.db_pool, conn, {
166+
let result: Vec<Webhook> = run_query!(
167+
state.db_pool,
168+
conn,
167169
webhooks
168170
.schema_name(&workspace_context.schema_name)
169-
.get_results(conn)
170-
})?;
171+
.get_results(&mut conn)
172+
)?;
171173
return Ok(Json(PaginatedResponse::all(result)));
172174
}
173175

@@ -177,7 +179,7 @@ async fn list_handler(
177179
webhooks
178180
.count()
179181
.schema_name(&workspace_context.schema_name)
180-
.get_result(conn)
182+
.get_result(&mut conn)
181183
)?;
182184
let limit = pagination.count.unwrap_or(10);
183185
let mut builder = webhooks
@@ -189,7 +191,7 @@ async fn list_handler(
189191
let offset = (page - 1) * limit;
190192
builder = builder.offset(offset);
191193
}
192-
let data: Vec<Webhook> = run_query!(state.db_pool, conn, builder.load(conn))?;
194+
let data: Vec<Webhook> = run_query!(state.db_pool, conn, builder.load(&mut conn))?;
193195
let total_pages = (total_items as f64 / limit as f64).ceil() as i64;
194196

195197
Ok(Json(PaginatedResponse {
@@ -209,7 +211,7 @@ async fn delete_handler(
209211
) -> superposition::Result<HttpResponse> {
210212
let w_name: String = params.into_inner().into();
211213

212-
run_query!(state.db_pool, tx conn, {
214+
run_tx_query!(state.db_pool, |conn: &mut DBConnection| {
213215
diesel::update(webhooks::table)
214216
.filter(webhooks::name.eq(&w_name))
215217
.set((
@@ -233,11 +235,13 @@ async fn get_by_event_handler(
233235
state: Data<AppState>,
234236
) -> superposition::Result<Json<Webhook>> {
235237
let event = params.into_inner();
236-
let webhook_row = run_query!(state.db_pool, conn, {
238+
let webhook_row = run_query!(
239+
state.db_pool,
240+
conn,
237241
webhooks
238242
.filter(webhooks::events.contains(vec![event]))
239243
.schema_name(&workspace_context.schema_name)
240-
.first(conn)
241-
})?;
244+
.first(&mut conn)
245+
)?;
242246
Ok(Json(webhook_row))
243247
}

0 commit comments

Comments
 (0)