Skip to content

Commit 8777065

Browse files
Convex, Incnipunn1313
authored andcommitted
Updates to convex-rs
GitOrigin-RevId: b27f3b383f2a8a1f84d558c33c5b327ad2b94b13
1 parent afc3fca commit 8777065

File tree

23 files changed

+193
-275
lines changed

23 files changed

+193
-275
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Upcoming
22

3+
# 0.6.0
4+
5+
- Remove support for Set and Map Convex types. These types are deprecated.
6+
- Add comprehensive support for ConvexError with `data` payload as part of the
7+
`FunctionResult` enum.
8+
- Better support for emitting loglines
9+
310
# 0.5.0
411

512
- Prelim support for ConvexError, encoded into an anyhow::Error. Eventual plan

Cargo.toml

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "convex"
33
description = "Client library for Convex (convex.dev)"
44
authors = [ "Convex, Inc. <team@convex.dev>" ]
5-
version = "0.5.0"
5+
version = "0.6.0"
66
edition = "2021"
77
rust-version = "1.65.0"
88
resolver = "2"
@@ -15,26 +15,25 @@ anyhow = { version = "1" }
1515
async-trait = { version = "0.1" }
1616
base64 = { version = "0.13" }
1717
bytes = { version = "1.1.0" }
18-
convex_sync_types = { path = "./sync_types", version = "=0.5.0" }
19-
derive_more = { version = "0.99" }
18+
convex_sync_types = { path = "./sync_types", version = "=0.6.0" }
2019
futures = { version = "0.3" }
2120
imbl = { version = "2.0.0" }
2221
parking_lot = { optional = true, version = "0.12" }
2322
proptest = { optional = true, version = "1" }
2423
proptest-derive = { optional = true, version = "0.4.0" }
2524
rand = { version = "0.8" }
26-
serde = { features = [ "derive" ], version = "1" }
2725
serde_json = { features = [ "float_roundtrip", "preserve_order" ], version = "1" }
26+
thiserror = { version = "1" }
2827
tokio = { features = [ "full" ], version = "1" }
2928
tokio-stream = { features = [ "io-util", "sync" ], version = "^0.1.8" }
30-
tokio-tungstenite = { version = "0.18.0" }
29+
tokio-tungstenite = { version = "0.20.0" }
3130
tracing = { version = "0.1" }
3231
url = { version = "2" }
33-
uuid = { features = [ "serde", "v4" ], version = "1.4" }
32+
uuid = { features = [ "serde", "v4" ], version = "1.6" }
3433

3534
[dev-dependencies]
3635
colored = { version = "2" }
37-
convex_sync_types = { path = "./sync_types", version = "=0.5.0", features = [ "testing" ] }
36+
convex_sync_types = { path = "./sync_types", version = "=0.6.0", features = [ "testing" ] }
3837
dotenvy = { version = "0.15.7" }
3938
maplit = { version = "1" }
4039
parking_lot = { version = "0.12" }
@@ -49,4 +48,4 @@ native-tls = [ "tokio-tungstenite/native-tls" ]
4948
native-tls-vendored = [ "tokio-tungstenite/native-tls-vendored" ]
5049
rustls-tls-native-roots = [ "tokio-tungstenite/rustls-tls-native-roots" ]
5150
rustls-tls-webpki-roots = [ "tokio-tungstenite/rustls-tls-webpki-roots" ]
52-
testing = [ "proptest", "proptest-derive", "parking_lot" ]
51+
testing = [ "convex_sync_types/testing", "proptest", "proptest-derive", "parking_lot" ]

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,8 @@ tracing_subscriber::fmt()
5656
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
5757
.init();
5858
```
59+
60+
By default, this will emit all logs, including internal logs from the client.
61+
Logs from your Convex backend will show up under the `convex_logs` target at
62+
Level=DEBUG. If you want to isolate just those logs, please refer to the
63+
[tracing_subscriber documentation](https://docs.rs/tracing-subscriber/latest/tracing_subscriber/layer/index.html#filtering-with-layers).

examples/convex_chat_client.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ async fn main() -> anyhow::Result<()> {
162162
FunctionResult::ErrorMessage(err) => {
163163
println!("{}.", err.red().bold());
164164
},
165+
FunctionResult::ConvexError(err) => {
166+
println!("{:?}", err);
167+
},
165168
};
166169
}
167170

examples/quickstart/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"dependencies": {
3-
"convex": "^0.13.0"
3+
"convex": "1.8.0"
44
}
55
}

src/base_client/mod.rs

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,13 @@ use tokio::sync::oneshot;
3232
#[cfg(doc)]
3333
use crate::ConvexClient;
3434
use crate::{
35+
convex_logs,
3536
sync::{
3637
ReconnectProtocolReason,
3738
ServerMessage,
3839
},
3940
value::Value,
41+
ConvexError,
4042
};
4143

4244
mod request_manager;
@@ -71,7 +73,7 @@ struct Query {
7173
}
7274

7375
/// An identifier for a single subscriber to a query.
74-
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord)]
76+
#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, Hash)]
7577
#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
7678
pub struct SubscriberId(QueryId, usize);
7779

@@ -165,7 +167,7 @@ impl LocalSyncState {
165167
None => panic!("INTERNAL BUG: Unknown query id {query_id}"),
166168
Some(t) => t,
167169
};
168-
let mut local_query = match self.query_set.get_mut(&query_token) {
170+
let local_query = match self.query_set.get_mut(&query_token) {
169171
None => panic!("INTERNAL BUG: No query found for query token {query_token:?}",),
170172
Some(q) => q,
171173
};
@@ -273,7 +275,8 @@ impl RemoteQuerySet {
273275
start_version,
274276
end_version,
275277
modifications,
276-
} = transition else {
278+
} = transition
279+
else {
277280
panic!("not transition");
278281
};
279282
if start_version != self.version {
@@ -290,22 +293,33 @@ impl RemoteQuerySet {
290293
StateModification::QueryUpdated {
291294
query_id,
292295
value,
293-
log_lines: _,
296+
log_lines,
294297
journal: _,
295298
} => {
299+
for log_line in log_lines.0 {
300+
convex_logs!("{}", log_line);
301+
}
296302
self.remote_query_set
297303
.insert(query_id, FunctionResult::Value(value));
298304
},
299305
StateModification::QueryFailed {
300306
query_id,
301307
error_message,
302-
log_lines: _,
308+
log_lines,
303309
journal: _,
304-
// TODO @srb: Implement ConvexError in Rust client queries
305-
error_data: _,
310+
error_data,
306311
} => {
307-
self.remote_query_set
308-
.insert(query_id, FunctionResult::ErrorMessage(error_message));
312+
for log_line in log_lines.0 {
313+
convex_logs!("{}", log_line);
314+
}
315+
let function_result = match error_data {
316+
Some(v) => FunctionResult::ConvexError(ConvexError {
317+
message: error_message,
318+
data: v,
319+
}),
320+
None => FunctionResult::ErrorMessage(error_message),
321+
};
322+
self.remote_query_set.insert(query_id, function_result);
309323
},
310324
StateModification::QueryRemoved { query_id } => {
311325
self.remote_query_set.remove(&query_id);
@@ -368,7 +382,7 @@ impl OptimisticQueryResults {
368382
/// The main methods, [`subscribe`](Self::subscribe()),
369383
/// [`unsubscribe`](Self::unsubscribe()), and
370384
/// [`mutation`](Self::mutation()) directly correspond to its
371-
/// equivalent for the external [ConvexClient](crate::ConvexClient).
385+
/// equivalent for the external [ConvexClient].
372386
///
373387
/// The only different method is [`get_query`](Self::get_query()), which
374388
/// returns the current value for a query given its query id. This method can be
@@ -583,22 +597,16 @@ impl BaseConvexClient {
583597
}
584598
return Ok(Some(self.state.latest_results.clone()));
585599
},
586-
ServerMessage::QueriesFailed { failures } => {
587-
// Note that we never expect to receive this as it is not sent by the server.
588-
for failure in failures {
589-
tracing::error![failure.message];
590-
}
591-
tracing::error!(
592-
"Received unexpected QueriesFailed from server. Restarting protocol."
593-
);
594-
return Err("QueriesFailed, see tracing::error for more details.".to_string());
595-
},
596600
ServerMessage::MutationResponse {
597601
request_id,
598602
result,
599603
ts,
600-
log_lines: _,
604+
log_lines,
601605
} => {
606+
for log_line in log_lines.0 {
607+
convex_logs!("{}", log_line);
608+
}
609+
602610
if let Some(ts) = ts {
603611
self.observe_timestamp(ts);
604612
}
@@ -629,8 +637,11 @@ impl BaseConvexClient {
629637
ServerMessage::ActionResponse {
630638
request_id,
631639
result,
632-
log_lines: _,
640+
log_lines,
633641
} => {
642+
for log_line in log_lines.0 {
643+
convex_logs!("{}", log_line);
644+
}
634645
let request_id = RequestId::new(request_id);
635646
self.request_manager.update_request(
636647
&request_id,
@@ -672,9 +683,7 @@ impl BaseConvexClient {
672683
let remote_query_results = &self.remote_query_set.remote_query_set;
673684
let mut query_id_to_value = BTreeMap::new();
674685
for (query_id, result) in remote_query_results.iter() {
675-
let Some(_udf_path) = self
676-
.state
677-
.query_path(*query_id) else {
686+
let Some(_udf_path) = self.state.query_path(*query_id) else {
678687
// It's possible that we've already unsubscribed to this query but
679688
// the server hasn't learned about that yet. If so, ignore this one.
680689
continue;
@@ -701,3 +710,17 @@ impl BaseConvexClient {
701710
self.optimistic_query_results.query_result(query_id)
702711
}
703712
}
713+
714+
/// Macro used for piping UDF logs to a custom formatter that exposes
715+
/// just the log content, without any additional Rust metadata.
716+
#[macro_export]
717+
macro_rules! convex_logs {
718+
(target: $target:expr, $($arg:tt)+) => {
719+
tracing::event!(target: "convex_logs", tracing::Level::DEBUG, $($arg)+);
720+
// Additional custom behavior can be added here
721+
};
722+
($($arg:tt)+) => {
723+
tracing::event!(target: "convex_logs", tracing::Level::DEBUG, $($arg)+);
724+
// Additional custom behavior can be added here
725+
};
726+
}

src/base_client/query_result.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use imbl::{
88
};
99

1010
use super::SubscriberId;
11-
use crate::Value;
11+
use crate::{
12+
ConvexError,
13+
Value,
14+
};
1215

1316
/// Result of a Convex function (query/mutation/action).
1417
///
@@ -20,14 +23,19 @@ pub enum FunctionResult {
2023
/// The error message of a Convex function run that does not complete
2124
/// successfully.
2225
ErrorMessage(String),
26+
/// The error payload of a Convex function run that doesn't complete
27+
/// successfully, with an application-level error.
28+
ConvexError(ConvexError),
2329
}
2430

2531
impl From<Result<Value, ErrorPayload<Value>>> for FunctionResult {
2632
fn from(result: Result<Value, ErrorPayload<Value>>) -> Self {
2733
match result {
2834
Ok(value) => FunctionResult::Value(value),
29-
// TODO @srb: Implement ConvexError in Rust client
30-
Err(error) => FunctionResult::ErrorMessage(error.get_message().to_owned()),
35+
Err(ErrorPayload::ErrorData { message, data }) => {
36+
FunctionResult::ConvexError(ConvexError { message, data })
37+
},
38+
Err(ErrorPayload::Message(message)) => FunctionResult::ErrorMessage(message),
3139
}
3240
}
3341
}
@@ -36,8 +44,11 @@ impl From<FunctionResult> for Result<Value, ErrorPayload<Value>> {
3644
fn from(result: FunctionResult) -> Self {
3745
match result {
3846
FunctionResult::Value(value) => Ok(value),
39-
// TODO @srb: Implement ConvexError in Rust client
4047
FunctionResult::ErrorMessage(error) => Err(ErrorPayload::Message(error)),
48+
FunctionResult::ConvexError(error) => Err(ErrorPayload::ErrorData {
49+
message: error.message,
50+
data: error.data,
51+
}),
4152
}
4253
}
4354
}
@@ -47,6 +58,9 @@ impl std::fmt::Debug for FunctionResult {
4758
match self {
4859
FunctionResult::Value(value) => f.debug_tuple("Value").field(value).finish(),
4960
FunctionResult::ErrorMessage(error) => write!(f, "{error}"),
61+
FunctionResult::ConvexError(error) => {
62+
f.debug_tuple("ConvexError").field(error).finish()
63+
},
5064
}
5165
}
5266
}

src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@
4444
mod value;
4545
#[cfg(any(test, feature = "testing"))]
4646
pub use value::export::roundtrip::ExportContext;
47-
pub use value::Value;
47+
pub use value::{
48+
ConvexError,
49+
Value,
50+
};
4851

4952
mod client;
5053
pub use client::{

src/sync/web_socket_manager.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ impl WebSocketWorker {
229229
let server_message = json.try_into()?;
230230
match server_message {
231231
ServerMessage::Ping => tracing::trace!("received message {server_message:?}"),
232-
_ => tracing::debug!("received message {server_message:?}"),
232+
_ => tracing::trace!("received message {server_message:?}"),
233233
};
234234

235235
let resp = ProtocolResponse::ServerMessage(server_message);

src/value/export/mod.rs

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ impl Value {
5353
Value::Array(values) => {
5454
JsonValue::Array(values.into_iter().map(|x| x.export()).collect())
5555
},
56-
// Use the internal representation for deprecated types
57-
Value::Set(_) | Value::Map(_) => self.into(),
5856
Value::Object(map) => JsonValue::Object(
5957
map.into_iter()
6058
.map(|(key, value)| (key, value.export()))
@@ -66,10 +64,7 @@ impl Value {
6664

6765
#[cfg(test)]
6866
mod tests {
69-
use maplit::{
70-
btreemap,
71-
btreeset,
72-
};
67+
use maplit::btreemap;
7368
use serde_json::json;
7469

7570
use super::*;
@@ -193,42 +188,4 @@ mod tests {
193188
}),
194189
);
195190
}
196-
197-
#[test]
198-
fn maps_use_the_internal_representation() {
199-
assert_eq!(
200-
Value::Map(btreemap! {
201-
"a".into() => 1.into(),
202-
"b".into() => 2.into(),
203-
"c".into() => 3.into(),
204-
})
205-
.export(),
206-
json!({
207-
"$map": [
208-
["a", { "$integer": "AQAAAAAAAAA=" }],
209-
["b", { "$integer": "AgAAAAAAAAA=" }],
210-
["c", { "$integer": "AwAAAAAAAAA=" }],
211-
],
212-
}),
213-
);
214-
}
215-
216-
#[test]
217-
fn sets_use_the_internal_representation() {
218-
assert_eq!(
219-
Value::Set(btreeset! {
220-
1.into(),
221-
2.into(),
222-
3.into(),
223-
})
224-
.export(),
225-
json!({
226-
"$set": [
227-
{ "$integer": "AQAAAAAAAAA=" },
228-
{ "$integer": "AgAAAAAAAAA=" },
229-
{ "$integer": "AwAAAAAAAAA=" },
230-
],
231-
}),
232-
);
233-
}
234191
}

0 commit comments

Comments
 (0)