-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: aes 287 create conclusion event type #499
Conversation
conclusion-event/cargo.toml
Outdated
@@ -0,0 +1,44 @@ | |||
[package] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will remove this directory, committed by mistake
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking great! Some questions below to get us started on the details
flight/src/types.rs
Outdated
// TODO : rethink this, add a checkpoint to make it work in datafusion query | ||
pub previous: Vec<Cid>, | ||
pub before: Option<CeramicTime>, | ||
pub after: Option<CeramicTime>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets remove both before
and after
from the data events. We have decided that we are not going to support conclusions about the temporality of data events. Consumers of the feed can make their own conclusions when a time event is emitted.
flight/src/types.rs
Outdated
// WIP : Need clearer structure for time events | ||
pub before: Option<CeramicTime>, | ||
pub after: Option<CeramicTime>, | ||
pub data: ByteBuf, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the data
for a time event? I don't think we need this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proof of anchor maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you just need the timestamp
flight/src/types.rs
Outdated
pub struct TimeEvent { | ||
// WIP : Need clearer structure for time events | ||
pub before: Option<CeramicTime>, | ||
pub after: Option<CeramicTime>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets remove before
and after
for the time events, we can add them back in later. We do not need the time information yet. Knowing the before and after fields requires we are validating time events. Once event validation completes we can implement these more directly.
flight/src/types.rs
Outdated
pub before: Option<CeramicTime>, | ||
pub after: Option<CeramicTime>, | ||
pub data: ByteBuf, | ||
pub id: Cid, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a prev
for the time event so we know which event it follows.
pub id: Cid, | ||
pub init: ConclusionInit, | ||
// TODO : rethink this, add a checkpoint to make it work in datafusion query | ||
pub previous: Vec<Cid>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW I am close to figuring this out....
flight/src/types.rs
Outdated
#[derive(Debug, Clone, Serialize, Deserialize)] | ||
pub struct ConclusionInit { | ||
pub stream_type: String, | ||
pub controllers: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should rename this to controller
since we are stating there is only ever going to be one?
flight/src/conversion.rs
Outdated
/// ``` | ||
pub fn conclusion_events_to_record_batch(events: &[ConclusionEvent]) -> Result<RecordBatch> { | ||
let schema = Arc::new(Schema::new(vec![ | ||
Field::new("event_type", DataType::Utf8, false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we use an integer type here instead as it is expected to be an enumeration of types?
flight/src/conversion.rs
Outdated
let schema = Arc::new(Schema::new(vec![ | ||
Field::new("event_type", DataType::Utf8, false), | ||
Field::new("stream_id", DataType::Binary, false), | ||
Field::new("stream_type", DataType::Utf8, false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here we should use an integer large enough to handle all future stream type values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uint8 should be good? we wont need more than 256 types i think
flight/src/conversion.rs
Outdated
true, | ||
), | ||
Field::new("data", DataType::Binary, false), | ||
])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need previous and it should be a list of binary values.
flight/src/conversion.rs
Outdated
let mut controllers = Vec::new(); | ||
let mut befores = Vec::new(); | ||
let mut afters = Vec::new(); | ||
let mut data = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can avoid allocating the vectors and then reallocating the same data into the Arrow arrays if we use their builders. See for an example https://github.com/ceramicnetwork/rust-ceramic/blob/feat/olap-udaf/olap/src/aggregator/ceramic_car.rs#L86-L135
I know I mislead a bit on this with the initial code example I sent. However the change to the builder pattern should be very similar to what you already have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I found this example in the Arrow docs. I really like the use of the Extend trait here https://arrow.apache.org/rust/arrow_array/builder/index.html#custom-builders Might be nice to follow this pattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for sharing the example, it was super helpful!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes are headed in the right direction. A few more comments below.
flight/src/conversion.rs
Outdated
let mut controllers = Vec::new(); | ||
let mut befores = Vec::new(); | ||
let mut afters = Vec::new(); | ||
let mut data = Vec::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I found this example in the Arrow docs. I really like the use of the Extend trait here https://arrow.apache.org/rust/arrow_array/builder/index.html#custom-builders Might be nice to follow this pattern
flight/src/conversion.rs
Outdated
// TODO: We should be able to set nullable as false in the field. But doing so breaks the ListBuilder :( | ||
Field::new( | ||
"previous", | ||
DataType::List(Box::new(Field::new("item", DataType::Binary, true))), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like we should be using with_field on the builder to override the field to match here.
flight/src/conversion.rs
Outdated
let mut stream_type_builder = UInt8Builder::new(events.len()); | ||
let mut controller_builder = StringBuilder::new(events.len()); | ||
let mut data_builder = BinaryBuilder::new(events.len()); | ||
let mut previous_builder = ListBuilder::new(BinaryBuilder::new(events.len())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using with_field here to match
flight/src/types.rs
Outdated
|
||
// TODO_Discussion: Do we still support all these types? | ||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | ||
pub enum StreamType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a type like this already in ceramic-core
. Can we re_use the same type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought the goal was that the core protocol didn't need to know anything about streamtypes. Can the flight API just pass through the streamtype as an integer without knowing anything about what it represents? The aggregator will of course need to be able to interpret the streamtype and know what it means, but does the conclusion feed need that level of knowledge?
As written now, if C1 started seeing events with a new streamtype, would the conclusion feed break? I don't think we want that, it should be possible to use an unmodified C1 with a custom aggregator that supports a new custom streamtype without needing to update C1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah the custom feed would break in this code with a Unknown Stream Type error. We can make the Conclusion Feed unaware of stream types and have it just store whatever stream type it gets in the database? But this means we might be storing arbitrary stream types. Is that what we want?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah this is a good question. If a user writes a custom aggregator with a new streamtype and starts using it, but neglects to update the streamtype table to reserve the id number for their new streamtype, what should happen? It would be kind of nice if C1 enforced that every event belongs to some registered streamtype, without caring which. I could imagine in the future C1 loading the streamtype list at startup and rejecting events with unregistred streamtypes. So maybe for now we should just have a hardcoded list of acceptable ID numbers and enforce that the streamtype we see in the allowed set?
But still without parsing or interpreting which specific streamtype id is used, just validating that it is one of the valid ones.
WDYT @nathanielc? Open to pushback or other ideas here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this code doesn't care which stream type it is and just need to pass that information along. If we want to validate stream types on ingest we can do that as part of the ceramic-service validation logic.
The conclusion feed should treat it as an opaque integer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, agreed in the context of this PR nothing more to do, I was more trying to ask the question in general of how we think this should be handled. If we think it's a good idea to validate that incoming events are part of a known streamtype, I can add a ticket to the Event Validation project to do that.
flight/src/types.rs
Outdated
} | ||
|
||
pub type CeramicTime = chrono::DateTime<chrono::Utc>; | ||
pub type Ipld = ByteBuf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this for? Its confusing to me to rename a byte buffer to Ipld
flight/src/conversion.rs
Outdated
Field::new("stream_id", DataType::Binary, false), | ||
Field::new("stream_type", DataType::UInt8, false), | ||
Field::new("controller", DataType::Utf8, false), | ||
Field::new("data", DataType::Binary, false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also need the dimensions column. This can be a list of fixed size list of two elements (i.e. key value pairs)
flight/src/conversion.rs
Outdated
/// Err(e) => eprintln!("Error creating RecordBatch: {}", e), | ||
/// } | ||
/// ``` | ||
pub fn conclusion_events_to_record_batch(events: &[ConclusionEvent]) -> Result<RecordBatch> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you create a ConclusionEventBuilder type and have it implement the Extends trait like shown here https://arrow.apache.org/rust/arrow_array/builder/index.html#custom-builders? That will make this API work well with lots of different collections of ConclusionEvents instead of just slices.
@@ -20,6 +20,7 @@ members = [ | |||
"beetle/iroh-util", | |||
"service", | |||
"olap", | |||
"flight", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add ceramic-flight as a dep below?
flight/Cargo.toml
Outdated
@@ -0,0 +1,24 @@ | |||
[package] | |||
name = "flight" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, rename to ceramic-flight
flight/Cargo.toml
Outdated
cid.workspace = true | ||
serde.workspace = true | ||
serde_bytes.workspace = true | ||
arrow = "9.0.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also, just noticed this. It should be arrow.workspace=true
so all crates are using the same arrow version (i.e. 52)
flight/src/types.rs
Outdated
|
||
#[derive(Debug, Clone, Serialize, Deserialize)] | ||
pub struct ConclusionData { | ||
pub id: Cid, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need both the Cid of the init event and the Cid of the event itself.
I suggest field names, stream_cid
and event_cid
. We will also need both of these as columns on the data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I include an id field in the conclusionInit struct?
How will the strem_cid be different than the event_cid?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dimension in the init will include the id of init event? CMIIW
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The stream_cid
is the CID of the init event of the stream. The event_cid
is the CID of the event itself.
flight/src/types.rs
Outdated
|
||
use cid::Cid; | ||
use serde::{Deserialize, Serialize}; | ||
use serde_bytes::ByteBuf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need serde
for these types? Can we use a simple Vec instead of the ByteBuf since we are serializing or deserializing these types?
flight/src/conversion.rs
Outdated
/// - event_type: UInt8, non-nullable | ||
/// - stream_id: Binary, non-nullable | ||
/// - stream_type: UInt8, non-nullable | ||
/// - controllers: Utf8, non-nullable (comma-separated list for Data events) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can probably just have a single "controller" instead of "controllers"
flight/src/types.rs
Outdated
|
||
// TODO_Discussion: Do we still support all these types? | ||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] | ||
pub enum StreamType { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought the goal was that the core protocol didn't need to know anything about streamtypes. Can the flight API just pass through the streamtype as an integer without knowing anything about what it represents? The aggregator will of course need to be able to interpret the streamtype and know what it means, but does the conclusion feed need that level of knowledge?
As written now, if C1 started seeing events with a new streamtype, would the conclusion feed break? I don't think we want that, it should be possible to use an unmodified C1 with a custom aggregator that supports a new custom streamtype without needing to update C1.
flight/src/tests.rs
Outdated
@@ -22,25 +20,24 @@ fn test_conclusion_events_to_record_batch() { | |||
ConclusionEvent::Data(ConclusionData { | |||
id: Cid::default(), | |||
init: ConclusionInit { | |||
stream_type: StreamType::Tile, | |||
stream_type: 0, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually think using named StreamTypes in test code is still nice and improves readability (assuming we have an existing type we can re-use, probably not worth adding one just for use in the tests). I'm only concerned about keeping the concrete streamtypes out of the production code, not the test code.
We should probably use MIDs in our tests though not TileDocuments since C1 doesn't actually support TileDocuments.
4c61204
to
8188d0c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the new builder pattern it came together well. Once we implement time events this should be good to go.
flight/Cargo.toml
Outdated
serde.workspace = true | ||
chrono = { version = "0.4", features = ["serde"] } | ||
arrow.workspace = true | ||
ceramic-core = { path = "../core" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, can you depend on the workspace version of ceramic-core?
flight/src/conversion.rs
Outdated
self.previous.append(true); | ||
} | ||
ConclusionEvent::Time(_) => { | ||
todo!("implement time event once we know what its structure looks like"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we will need this now, can you add an implementation and we can discuss?
flight/src/conversion.rs
Outdated
let controller_field = Arc::new(Field::new("controller", DataType::Utf8, false)); | ||
|
||
let data = Arc::new(self.data.finish()) as ArrayRef; | ||
let data_field = Arc::new(Field::new("data", DataType::Binary, false)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The data
field will need to be nullable because time events will not have data values.
flight/src/conversion.rs
Outdated
fn default() -> Self { | ||
Self { | ||
event_type: PrimitiveBuilder::new(), | ||
stream_id: BinaryBuilder::new(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, stream_id
to stream_cid
. A stream ID is an encoding of the stream type + its CID, since we have the stream type explicitly as a column on the data we only want the stream CID. So we should name the column accordingly.
flight/src/tests.rs
Outdated
assert_eq!(record_batch.num_rows(), 2); | ||
|
||
// Assert the schema | ||
let schema = record_batch.schema(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets validate these tests using the expect_test
pattern. This way they are much easier to audit and update.
You can convert a RecordBatch into string like this https://github.com/ceramicnetwork/rust-ceramic/pull/500/files#diff-eb701a6fc846dc0a4b096209cdf1b5b1a75028561fcc2e3c6629862757eec348R287
Then you can use expect!
like this to validate its what we expect https://github.com/ceramicnetwork/rust-ceramic/pull/500/files#diff-eb701a6fc846dc0a4b096209cdf1b5b1a75028561fcc2e3c6629862757eec348R310-R315
If you haven't used expect_test before I recommend a quick read on how to use it and update tests https://docs.rs/expect-test/latest/expect_test/#introduction
flight/src/types.rs
Outdated
pub type CeramicTime = chrono::DateTime<chrono::Utc>; | ||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)] | ||
pub struct TimeEvent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets rename this to ConclusionTime to be consistent
// WIP : Need clearer structure for time events | ||
pub id: Cid, | ||
pub previous: Vec<Cid>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Time events need stream_cid
, stream_type
, event_cid
, controller
and previous
for now. We can add more later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should the bulk of those come in via a ConclusionInit
field, the same way that is done for data events? As opposed to including at the top-level directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think they should
flight/src/conversion.rs
Outdated
fn append(&mut self, event: &ConclusionEvent) { | ||
match event { | ||
ConclusionEvent::Data(data_event) => { | ||
self.event_type.append_value(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a method on ConclusionEvent that can report the type as an integer? This way the mapping of variant to integer type is explicit on the type instead of hidden in the conversion implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me with a fix to the test case.
flight/src/conversion.rs
Outdated
for cid in &time_event.previous { | ||
self.previous.values().append_value(cid.to_bytes()); | ||
} | ||
self.previous.append(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be self.previous.append(!time_event.previous.is_empty())
flight/src/conversion.rs
Outdated
for cid in &data_event.previous { | ||
self.previous.values().append_value(cid.to_bytes()); | ||
} | ||
self.previous.append(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be self.previous.append(!data_event.previous.is_empty())
flight/src/tests.rs
Outdated
+------------+--------------------------------------------------------------------------+-------------+---------------+--------------------------------------------------------------------------+--------+----------------------------------------------------------------------------+ | ||
| 0 | 01001220ba28cb0268f4f50cca99d952b610bfa2823941bfb12452ccf1e330725d96ae0d | 2 | did:key:test1 | 010012200b9691e769ef527bd51427fc745c8bfb8e89271e054548a780ddeed7817cbe0a | 010203 | [] | | ||
| 0 | 01001220ba28cb0268f4f50cca99d952b610bfa2823941bfb12452ccf1e330725d96ae0d | 2 | did:key:test2 | 010012200b9691e769ef527bd51427fc745c8bfb8e89271e054548a780ddeed7817cbe0a | 040506 | [01001220ba28cb0268f4f50cca99d952b610bfa2823941bfb12452ccf1e330725d96ae0d] | | ||
| 1 | 01001220ba28cb0268f4f50cca99d952b610bfa2823941bfb12452ccf1e330725d96ae0d | 2 | did:key:test3 | 010012200b9691e769ef527bd51427fc745c8bfb8e89271e054548a780ddeed7817cbe0a | | | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous column is empty here, however the input data does include a previous cid. This is caused by the bug I noted above.
flight/src/tests.rs
Outdated
data: vec![1, 2, 3], | ||
}), | ||
ConclusionEvent::Data(ConclusionData { | ||
event_cid: Cid::from_str("baeabeials2i6o2ppkj55kfbh7r2fzc73r2esohqfivekpag553lyc7f6bi") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use an unique CID for each event ? This will make auditing the expected results easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use cpk to generate random cids easily
flight/src/tests.rs
Outdated
event_cid: Cid::from_str("baeabeials2i6o2ppkj55kfbh7r2fzc73r2esohqfivekpag553lyc7f6bi") | ||
.unwrap(), | ||
previous: vec![Cid::from_str( | ||
"baeabeif2fdfqe2hu6ugmvgozkk3bbp5cqi4udp5rerjmz4pdgbzf3fvobu", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previous should be the CID of an event not a stream, can you make these chain so its easier to follow?
| 1 | 01001220ba28cb0268f4f50cca99d952b610bfa2823941bfb12452ccf1e330725d96ae0d | 2 | did:key:test3 | 010012200b9691e769ef527bd51427fc745c8bfb8e89271e054548a780ddeed7817cbe0a | | | | ||
| 0 | 01001220ba28cb0268f4f50cca99d952b610bfa2823941bfb12452ccf1e330725d96ae0d | 2 | did:key:test4 | 010012200b9691e769ef527bd51427fc745c8bfb8e89271e054548a780ddeed7817cbe0a | 070809 | [] | | ||
+------------+--------------------------------------------------------------------------+-------------+---------------+--------------------------------------------------------------------------+--------+----------------------------------------------------------------------------+"#]].assert_eq(&formatted); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure if it belongs in this test file. It seems like a lot of code for what we want to do, instead I added a method which converts cid bytes to string, for event_cid and stream_cid columns, which does the same thing
Open to push back
2221157
to
90629d8
Compare
Added a new flight crate, which currently holds conclusion event type and conversion logic to convert a feed of conclusion event to an arrow recordBatch. (https://docs.rs/arrow/latest/arrow/record_batch/struct.RecordBatch.html)
Type information is present here : https://www.notion.so/MVP-OLAP-Aggregator-on-Ceramic-Basin-74f26d19cc8b4f508dbda3a57204228a?d=331986c9e56846f48fd942f8ef7d66c9#89cf865fceec40aba4c6edafe955f5c4