Skip to content

Commit 25b0258

Browse files
committed
Make raw error private
1 parent 05ba512 commit 25b0258

File tree

11 files changed

+53
-43
lines changed

11 files changed

+53
-43
lines changed

crates/core/src/checkpoint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ fn powersync_validate_checkpoint_impl(
2727
) -> Result<String, PowerSyncError> {
2828
let data = args[0].text();
2929
let checkpoint: Checkpoint =
30-
serde_json::from_str(data).map_err(PowerSyncError::json_argument_error)?;
30+
serde_json::from_str(data).map_err(PowerSyncError::as_argument_error)?;
3131
let db = ctx.db_handle();
3232
let buckets: Vec<OwnedBucketChecksum> = checkpoint
3333
.buckets

crates/core/src/diff.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,8 @@ fn powersync_diff_impl(
2323
}
2424

2525
pub fn diff_objects(data_old: &str, data_new: &str) -> Result<String, PowerSyncError> {
26-
let v_new: json::Value =
27-
json::from_str(data_new).map_err(PowerSyncError::json_argument_error)?;
28-
let v_old: json::Value =
29-
json::from_str(data_old).map_err(PowerSyncError::json_argument_error)?;
26+
let v_new: json::Value = json::from_str(data_new).map_err(PowerSyncError::as_argument_error)?;
27+
let v_old: json::Value = json::from_str(data_old).map_err(PowerSyncError::as_argument_error)?;
3028

3129
if let (json::Value::Object(mut left), json::Value::Object(mut right)) = (v_new, v_old) {
3230
// Remove all null values

crates/core/src/error.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use crate::bson::BsonError;
1313

1414
/// A [RawPowerSyncError], but boxed.
1515
///
16-
/// We allocate errors in boxes to avoid large [Result] types returning these.
16+
/// We allocate errors in boxes to avoid large [Result] types (given the large size of the
17+
/// [RawPowerSyncError] enum type).
1718
pub struct PowerSyncError {
1819
inner: Box<RawPowerSyncError>,
1920
}
@@ -35,10 +36,14 @@ impl PowerSyncError {
3536
.into()
3637
}
3738

38-
pub fn json_argument_error(cause: serde_json::Error) -> Self {
39+
/// Converts something that can be a [PowerSyncErrorCause] into an argument error.
40+
///
41+
/// This can be used to represent e.g. JSON parsing errors as argument errors, e.g. with
42+
/// ` serde_json::from_str(payload.text()).map_err(PowerSyncError::as_argument_error)`.
43+
pub fn as_argument_error(cause: impl Into<PowerSyncErrorCause>) -> Self {
3944
RawPowerSyncError::ArgumentError {
4045
desc: "".into(),
41-
cause: PowerSyncErrorCause::Json(cause),
46+
cause: cause.into(),
4247
}
4348
.into()
4449
}
@@ -54,17 +59,35 @@ impl PowerSyncError {
5459
RawPowerSyncError::StateError { desc }.into()
5560
}
5661

62+
pub fn sync_protocol_error(desc: &'static str, cause: impl Into<PowerSyncErrorCause>) -> Self {
63+
RawPowerSyncError::SyncProtocolError {
64+
desc,
65+
cause: cause.into(),
66+
}
67+
.into()
68+
}
69+
70+
/// A generic internal error.
71+
///
72+
/// This should only be used rarely since this error provides no further details.
5773
pub fn unknown_internal() -> Self {
5874
Self::internal(PowerSyncErrorCause::Unknown)
5975
}
6076

77+
/// A generic internal error with an associated cause.
6178
pub fn internal(cause: impl Into<PowerSyncErrorCause>) -> Self {
6279
RawPowerSyncError::Internal {
6380
cause: cause.into(),
6481
}
6582
.into()
6683
}
6784

85+
pub fn missing_client_id() -> Self {
86+
RawPowerSyncError::MissingClientId.into()
87+
}
88+
89+
/// Applies this error to a function result context, setting the error code and a descriptive
90+
/// text.
6891
pub fn apply_to_ctx(self, description: &str, ctx: *mut context) {
6992
let mut desc = self.description(ctx.db_handle());
7093
desc.insert_str(0, description);
@@ -91,7 +114,7 @@ impl PowerSyncError {
91114

92115
match self.inner.as_ref() {
93116
Sqlite { code, .. } => *code,
94-
InvalidBucketPriority | ArgumentError { .. } | StateError { .. } => ResultCode::MISUSE,
117+
ArgumentError { .. } | StateError { .. } => ResultCode::MISUSE,
95118
MissingClientId | SyncProtocolError { .. } => ResultCode::ABORT,
96119
LocalDataError { .. } => ResultCode::CORRUPT,
97120
Internal { .. } => ResultCode::INTERNAL,
@@ -125,7 +148,7 @@ impl From<ResultCode> for PowerSyncError {
125148

126149
/// A structured enumeration of possible errors that can occur in the core extension.
127150
#[derive(Error, Debug)]
128-
pub enum RawPowerSyncError {
151+
enum RawPowerSyncError {
129152
/// An internal call to SQLite made by the core extension has failed. We store the original
130153
/// result code and an optional context describing what the core extension was trying to do when
131154
/// the error occurred.
@@ -158,19 +181,18 @@ pub enum RawPowerSyncError {
158181
/// (e.g. a checkpoint diff before we've ever received a checkpoint).
159182
///
160183
/// This interrupts a sync iteration as we cannot reasonably continue afterwards (the client and
161-
/// server are necessarily in different states).
184+
/// server are necessarily in diverged states).
162185
#[error("Sync protocol error: {desc}. {cause}")]
163186
SyncProtocolError {
164187
desc: &'static str,
165188
cause: PowerSyncErrorCause,
166189
},
167190
/// There's invalid local data in the database (like malformed JSON in the oplog table).
168-
#[error("invalid local data")]
191+
#[error("invalid local data: {cause}")]
169192
LocalDataError { cause: PowerSyncErrorCause },
170193
#[error("No client_id found in ps_kv")]
171194
MissingClientId,
172-
#[error("Invalid bucket priority value")]
173-
InvalidBucketPriority,
195+
/// A catch-all for remaining internal errors that are very unlikely to happen.
174196
#[error("Internal PowerSync error. {cause}")]
175197
Internal { cause: PowerSyncErrorCause },
176198
}

crates/core/src/kv.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use sqlite_nostd::{Connection, Context};
99

1010
use crate::create_sqlite_optional_text_fn;
1111
use crate::create_sqlite_text_fn;
12-
use crate::error::{PowerSyncError, RawPowerSyncError};
12+
use crate::error::PowerSyncError;
1313
use crate::sync::BucketPriority;
1414

1515
fn powersync_client_id_impl(
@@ -29,7 +29,7 @@ pub fn client_id(db: *mut sqlite::sqlite3) -> Result<String, PowerSyncError> {
2929
let client_id = statement.column_text(0)?;
3030
Ok(client_id.to_string())
3131
} else {
32-
Err(RawPowerSyncError::MissingClientId.into())
32+
Err(PowerSyncError::missing_client_id())
3333
}
3434
}
3535

crates/core/src/operations.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub fn insert_operation(db: *mut sqlite::sqlite3, data: &str) -> Result<(), Powe
1818
}
1919

2020
let batch: BucketBatch =
21-
serde_json::from_str(data).map_err(PowerSyncError::json_argument_error)?;
21+
serde_json::from_str(data).map_err(PowerSyncError::as_argument_error)?;
2222
let adapter = StorageAdapter::new(db)?;
2323

2424
for line in &batch.buckets {

crates/core/src/schema/management.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ SELECT name, internal_name, local_only FROM powersync_tables WHERE name NOT IN (
133133
fn update_indexes(db: *mut sqlite::sqlite3, schema: &str) -> Result<(), PowerSyncError> {
134134
let mut statements: Vec<String> = alloc::vec![];
135135
let schema =
136-
serde_json::from_str::<Schema>(schema).map_err(PowerSyncError::json_argument_error)?;
136+
serde_json::from_str::<Schema>(schema).map_err(PowerSyncError::as_argument_error)?;
137137
let mut expected_index_names: Vec<String> = vec![];
138138

139139
{

crates/core/src/sync/bucket_priority.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use serde::{de::Visitor, Deserialize, Serialize};
22

3-
use crate::error::{PowerSyncError, RawPowerSyncError};
3+
use crate::error::PowerSyncError;
44

55
#[repr(transparent)]
66
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -26,7 +26,9 @@ impl TryFrom<i32> for BucketPriority {
2626

2727
fn try_from(value: i32) -> Result<Self, Self::Error> {
2828
if value < BucketPriority::HIGHEST.number || value == Self::SENTINEL.number {
29-
return Err(RawPowerSyncError::InvalidBucketPriority.into());
29+
return Err(PowerSyncError::argument_error(
30+
"Invalid bucket priority value",
31+
));
3032
}
3133

3234
return Ok(BucketPriority { number: value });

crates/core/src/sync/interface.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ pub fn register(db: *mut sqlite::sqlite3, state: Arc<DatabaseState>) -> Result<(
151151
"start" => SyncControlRequest::StartSyncStream({
152152
if payload.value_type() == ColumnType::Text {
153153
serde_json::from_str(payload.text())
154-
.map_err(PowerSyncError::json_argument_error)?
154+
.map_err(PowerSyncError::as_argument_error)?
155155
} else {
156156
StartSyncStream::default()
157157
}

crates/core/src/sync/streaming_sync.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use futures_lite::FutureExt;
1717

1818
use crate::{
1919
bson,
20-
error::{PowerSyncError, RawPowerSyncError},
20+
error::PowerSyncError,
2121
kv::client_id,
2222
state::DatabaseState,
2323
sync::{checkpoint::OwnedBucketChecksum, interface::StartSyncStream},
@@ -249,18 +249,10 @@ impl StreamingSyncIteration {
249249
.update(|s| s.disconnect(), &mut event.instructions);
250250
break;
251251
}
252-
SyncEvent::TextLine { data } => serde_json::from_str(data).map_err(|e| {
253-
PowerSyncError::from(RawPowerSyncError::SyncProtocolError {
254-
desc: "invalid text line",
255-
cause: e.into(),
256-
})
257-
})?,
258-
SyncEvent::BinaryLine { data } => bson::from_bytes(data).map_err(|e| {
259-
PowerSyncError::from(RawPowerSyncError::SyncProtocolError {
260-
desc: "invalid binary line",
261-
cause: e.into(),
262-
})
263-
})?,
252+
SyncEvent::TextLine { data } => serde_json::from_str(data)
253+
.map_err(|e| PowerSyncError::sync_protocol_error("invalid text line", e))?,
254+
SyncEvent::BinaryLine { data } => bson::from_bytes(data)
255+
.map_err(|e| PowerSyncError::sync_protocol_error("invalid binary line", e))?,
264256
SyncEvent::UploadFinished => {
265257
if let Some(checkpoint) = validated_but_not_applied.take() {
266258
let result = self.adapter.sync_local(

crates/core/src/sync_local.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub fn sync_local<V: Value>(
2020
data: &V,
2121
) -> Result<i64, PowerSyncError> {
2222
let mut operation: SyncOperation<'_> =
23-
SyncOperation::from_args(state, db, data).map_err(PowerSyncError::json_argument_error)?;
23+
SyncOperation::from_args(state, db, data).map_err(PowerSyncError::as_argument_error)?;
2424
operation.apply()
2525
}
2626

0 commit comments

Comments
 (0)