Skip to content

Commit b4d42ac

Browse files
committed
fix: clippy and coderabbit suggestions
1 parent d5f1afe commit b4d42ac

9 files changed

Lines changed: 94 additions & 47 deletions

File tree

src/cli.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
*/
1818

19-
use clap::Parser;
19+
use clap::{Parser, value_parser};
2020
use std::{env, fs, path::PathBuf};
2121

2222
use url::Url;
@@ -170,10 +170,11 @@ pub struct Options {
170170
#[arg(
171171
long,
172172
env = "P_ACTIX_NUM_WORKERS",
173-
default_value_t = num_cpus::get(),
173+
default_value_t = num_cpus::get() as u64,
174+
value_parser = value_parser!(u64).range(1..),
174175
help = "Number of workers for actix-web"
175176
)]
176-
pub num_workers: usize,
177+
pub num_workers: u64,
177178

178179
// Actix connections backlog
179180
#[arg(

src/handlers/http/modal/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::{fmt, path::Path, sync::Arc, time::Duration};
2121
use actix_web::{App, HttpServer, http::KeepAlive, middleware::from_fn, web::ServiceConfig};
2222
use actix_web_prometheus::PrometheusMetrics;
2323
use anyhow::Context;
24+
use arrow::datatypes::ArrowNativeType;
2425
use async_trait::async_trait;
2526
use base64::{Engine, prelude::BASE64_STANDARD};
2627
use bytes::Bytes;
@@ -121,7 +122,7 @@ pub trait ParseableServer {
121122

122123
// Create the HTTP server
123124
let http_server = HttpServer::new(create_app_fn)
124-
.workers(PARSEABLE.options.num_workers)
125+
.workers(PARSEABLE.options.num_workers.as_usize())
125126
.keep_alive(KeepAlive::Timeout(Duration::from_secs(
126127
PARSEABLE.options.keep_alive,
127128
)))

src/handlers/http/modal/utils/ingest_utils.rs

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use opentelemetry_proto::tonic::{
2424
};
2525
use rayon::iter::{IntoParallelIterator, ParallelIterator};
2626
use serde_json::Value;
27-
use std::{collections::HashMap, ops::ControlFlow};
27+
use std::collections::HashMap;
2828
use tracing::{instrument, warn};
2929

3030
use crate::{
@@ -182,6 +182,12 @@ pub fn push_logs(
182182
log_source,
183183
)?;
184184

185+
if data.is_empty() {
186+
return Err(PostError::Invalid(anyhow::Error::msg(
187+
"Empty data object received",
188+
)));
189+
}
190+
185191
// Batch path: one schema inference + one decoder for the entire batch.
186192
// When custom partitions are set, different records may need different
187193
// partition keys, so fall back to per-record processing.
@@ -219,34 +225,29 @@ pub fn push_logs(
219225
event.process()?;
220226
} else {
221227
// Per-record path for custom-partitioned streams
222-
let r = data.into_par_iter().try_for_each(|json| {
223-
let origin_size = json_byte_size(&json);
224-
225-
match (json::Event { json, p_timestamp }).into_event(
226-
stream_name.to_owned(),
227-
origin_size,
228-
&schema,
229-
static_schema_flag,
230-
custom_partition.as_ref(),
231-
time_partition.as_ref(),
232-
schema_version,
233-
StreamType::UserDefined,
234-
p_custom_fields,
235-
telemetry_type,
236-
tenant_id,
237-
) {
238-
Ok(event) => match event.process() {
239-
Ok(_) => ControlFlow::Continue(()),
240-
Err(e) => ControlFlow::Break(e.into()),
241-
},
242-
Err(e) => ControlFlow::Break(e),
243-
}
244-
});
245-
if let ControlFlow::Break(e) = r {
246-
return Err(PostError::CustomError(e.to_string()));
228+
let events: Result<Vec<_>, _> = data
229+
.into_par_iter()
230+
.map(|json| {
231+
let origin_size = json_byte_size(&json);
232+
(json::Event { json, p_timestamp }).into_event(
233+
stream_name.to_owned(),
234+
origin_size,
235+
&schema,
236+
static_schema_flag,
237+
custom_partition.as_ref(),
238+
time_partition.as_ref(),
239+
schema_version,
240+
StreamType::UserDefined,
241+
p_custom_fields,
242+
telemetry_type,
243+
tenant_id,
244+
)
245+
})
246+
.collect();
247+
for event in events.map_err(PostError::Invalid)? {
248+
event.process()?;
247249
}
248250
}
249-
250251
Ok(())
251252
}
252253

src/otel/metrics.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,23 @@ pub fn flatten_metrics_record(metrics_record: &Metric) -> Vec<Map<String, Value>
460460
single.insert("metric_description".to_string(), metric_desc);
461461
single.insert("metric_unit".to_string(), metric_unit);
462462
single.insert("metric_type".to_string(), metric_type_val);
463+
match &metrics_record.data {
464+
Some(metric::Data::Sum(sum)) => {
465+
single.extend(flatten_aggregation_temporality(sum.aggregation_temporality));
466+
single.insert("is_monotonic".to_string(), Value::Bool(sum.is_monotonic));
467+
}
468+
Some(metric::Data::Histogram(histogram)) => {
469+
single.extend(flatten_aggregation_temporality(
470+
histogram.aggregation_temporality,
471+
));
472+
}
473+
Some(metric::Data::ExponentialHistogram(exp_histogram)) => {
474+
single.extend(flatten_aggregation_temporality(
475+
exp_histogram.aggregation_temporality,
476+
));
477+
}
478+
_ => {}
479+
}
463480
single.extend(metadata);
464481
return vec![single];
465482
}

src/parseable/staging/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
*
1818
*/
1919

20+
use std::sync::PoisonError;
21+
2022
use crate::{parseable::StreamNotFound, tenants::TenantNotFound};
2123

2224
pub mod reader;
@@ -36,6 +38,6 @@ pub enum StagingError {
3638
StreamNotFound(#[from] StreamNotFound),
3739
#[error("{0}")]
3840
TenantNotFound(#[from] TenantNotFound),
39-
// #[error("Metadata Error: {0}")]
40-
// Metadata(#[from] MetadataError),
41+
#[error("{0}")]
42+
PoisonError(#[from] PoisonError<String>),
4143
}

src/parseable/staging/reader.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ pub struct OffsetReader<R: Read + Seek> {
143143
}
144144

145145
impl<R: Read + Seek> OffsetReader<R> {
146-
fn _new(reader: R, offset_list: Vec<(u64, usize)>) -> Self {
146+
fn new(reader: R, offset_list: Vec<(u64, usize)>) -> Self {
147147
let mut offset_list = offset_list.into_iter();
148148
let mut finished = false;
149149

@@ -217,7 +217,7 @@ pub fn get_reverse_reader<T: Read + Seek>(
217217
let mut offset = 0;
218218
let mut messages = Vec::new();
219219

220-
while let Some(res) = _find_limit_and_type(&mut reader).transpose() {
220+
while let Some(res) = find_limit_and_type(&mut reader).transpose() {
221221
match res {
222222
Ok((header, size)) => {
223223
messages.push((header, offset, size));
@@ -238,11 +238,16 @@ pub fn get_reverse_reader<T: Read + Seek>(
238238
// reset reader
239239
reader.rewind()?;
240240

241-
Ok(StreamReader::try_new(BufReader::new(OffsetReader::_new(reader, messages)), None).unwrap())
241+
StreamReader::try_new(BufReader::new(OffsetReader::new(reader, messages)), None).map_err(|e| {
242+
io::Error::new(
243+
io::ErrorKind::InvalidData,
244+
format!("Invalid arrow stream: {e}"),
245+
)
246+
})
242247
}
243248

244249
// return limit for
245-
fn _find_limit_and_type(
250+
fn find_limit_and_type(
246251
reader: &mut (impl Read + Seek),
247252
) -> Result<Option<(MessageHeader, usize)>, io::Error> {
248253
let mut size = 0;
@@ -476,7 +481,7 @@ mod tests {
476481
// Define offset list: (offset, size)
477482
let offsets = vec![(2, 3), (7, 2)]; // Read bytes 2-4 (3, 4, 5) and then 7-8 (8, 9)
478483

479-
let mut reader = OffsetReader::_new(cursor, offsets);
484+
let mut reader = OffsetReader::new(cursor, offsets);
480485
let mut buffer = [0u8; 10];
481486

482487
// First read should get bytes 3, 4, 5
@@ -563,7 +568,7 @@ mod tests {
563568
let data = vec![1, 2, 3, 4, 5];
564569
let cursor = Cursor::new(data);
565570

566-
let mut reader = OffsetReader::_new(cursor, vec![]);
571+
let mut reader = OffsetReader::new(cursor, vec![]);
567572
let mut buffer = [0u8; 10];
568573

569574
// Should return 0 bytes read
@@ -580,7 +585,7 @@ mod tests {
580585
// One offset of 5 bytes
581586
let offsets = vec![(2, 5)]; // Read bytes 2-6 (3, 4, 5, 6, 7)
582587

583-
let mut reader = OffsetReader::_new(cursor, offsets);
588+
let mut reader = OffsetReader::new(cursor, offsets);
584589
let mut buffer = [0u8; 3]; // Buffer smaller than the 5 bytes we want to read
585590

586591
// First read should get first 3 bytes: 3, 4, 5
@@ -641,7 +646,7 @@ mod tests {
641646
// One large offset (8KB)
642647
let offsets = vec![(1000, 8000)];
643648

644-
let mut reader = OffsetReader::_new(cursor, offsets);
649+
let mut reader = OffsetReader::new(cursor, offsets);
645650
let mut buffer = [0u8; 10000];
646651

647652
// Should read 8KB

src/parseable/streams.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use parquet::{
3333
schema::types::ColumnPath,
3434
};
3535
use relative_path::RelativePathBuf;
36-
use std::io::BufReader;
3736
use std::{
3837
collections::{HashMap, HashSet},
3938
fs::{self, File, OpenOptions, remove_file, write},
@@ -42,6 +41,7 @@ use std::{
4241
sync::{Arc, Mutex, RwLock},
4342
time::{Instant, SystemTime, UNIX_EPOCH},
4443
};
44+
use std::{io::BufReader, sync::PoisonError};
4545
use tokio::task::JoinSet;
4646
use tracing::{Instrument, error, info, info_span, instrument, trace, warn};
4747
use ulid::Ulid;
@@ -162,7 +162,11 @@ impl Stream {
162162
"Writer lock poisoned while ingesting data for stream {}",
163163
self.stream_name
164164
);
165-
poisoned.into_inner()
165+
166+
return Err(StagingError::PoisonError(PoisonError::new(format!(
167+
"Writer lock poisoned while ingesting data for stream {} - {}",
168+
self.stream_name, poisoned
169+
))));
166170
}
167171
}
168172
};

src/sync.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ use tracing::{Instrument, error, info, info_span, trace, warn};
3131
static LOCAL_SYNC_RUNNING: AtomicBool = AtomicBool::new(false);
3232
static REMOTE_SYNC_RUNNING: AtomicBool = AtomicBool::new(false);
3333

34+
/// RAII guard that clears a sync-running flag on drop, so a panic inside the
35+
/// sync body cannot leave the flag stuck at `true` and wedge future ticks.
36+
struct SyncRunningGuard(&'static AtomicBool);
37+
38+
impl Drop for SyncRunningGuard {
39+
fn drop(&mut self) {
40+
self.0.store(false, Ordering::SeqCst);
41+
}
42+
}
43+
3444
use crate::alerts::alert_enums::AlertTask;
3545
use crate::alerts::alerts_utils;
3646
use crate::parseable::PARSEABLE;
@@ -135,6 +145,7 @@ pub fn object_store_sync() -> (
135145
warn!("Previous object_store_sync cycle still running, skipping this tick");
136146
continue;
137147
}
148+
let _guard = SyncRunningGuard(&REMOTE_SYNC_RUNNING);
138149
async {
139150
trace!("Syncing Parquets to Object Store... ");
140151

@@ -153,7 +164,6 @@ pub fn object_store_sync() -> (
153164
}
154165
).await;
155166
}.instrument(info_span!("object_store_sync_cycle")).await;
156-
REMOTE_SYNC_RUNNING.store(false, Ordering::SeqCst);
157167
},
158168
res = &mut inbox_rx => {
159169
match res {
@@ -209,6 +219,7 @@ pub fn local_sync() -> (
209219
warn!("Previous local_sync cycle still running, skipping this tick");
210220
continue;
211221
}
222+
let _guard = SyncRunningGuard(&LOCAL_SYNC_RUNNING);
212223
// Monitor the duration of flush_and_convert execution
213224
async {
214225
monitor_task_duration(
@@ -225,7 +236,6 @@ pub fn local_sync() -> (
225236
}
226237
).await;
227238
}.instrument(info_span!("local_sync_cycle")).await;
228-
LOCAL_SYNC_RUNNING.store(false, Ordering::SeqCst);
229239
},
230240
res = &mut inbox_rx => {
231241
match res {

src/telemetry.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ use opentelemetry_sdk::{
2626
};
2727
// Consts describing the env vars
2828
const OTEL_EXPORTER_OTLP_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_ENDPOINT";
29+
const OTEL_EXPORTER_OTLP_TRACES_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT";
2930
const OTEL_EXPORTER_OTLP_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_PROTOCOL";
31+
3032
/// Initialise an OTLP tracer provider.
3133
///
3234
/// **Required env var:**
@@ -45,12 +47,16 @@ const OTEL_EXPORTER_OTLP_PROTOCOL: &str = "OTEL_EXPORTER_OTLP_PROTOCOL";
4547
/// as gRPC metadata or HTTP headers, e.g.
4648
/// \`authorization=Basic <token>,x-p-stream=my-stream,x-p-log-source=otel-traces\`
4749
///
48-
/// Returns \`None\` when \`OTEL_EXPORTER_OTLP_ENDPOINT\` is not set (OTEL disabled).
50+
/// Returns \`None\` when \`OTEL_EXPORTER_OTLP_ENDPOINT\` or `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` is not set (OTEL disabled).
4951
/// The caller must call \`provider.shutdown()\` before process exit.
5052
pub fn init_tracing() -> Option<SdkTracerProvider> {
5153
// Only used to decide whether OTEL is enabled; the SDK reads it again
5254
// from env to build the exporter (which also appends /v1/traces for HTTP).
53-
std::env::var(OTEL_EXPORTER_OTLP_ENDPOINT).ok()?;
55+
if std::env::var(OTEL_EXPORTER_OTLP_ENDPOINT).is_err()
56+
&& std::env::var(OTEL_EXPORTER_OTLP_TRACES_ENDPOINT).is_err()
57+
{
58+
return None;
59+
}
5460

5561
let protocol =
5662
std::env::var(OTEL_EXPORTER_OTLP_PROTOCOL).unwrap_or_else(|_| "http/json".to_string());

0 commit comments

Comments
 (0)