amazon-ion / ion-rust

Rust implementation of Amazon Ion
Apache License 2.0
150 stars 36 forks source link

v1_1 `Writer::flush()` seems to not empty the buffer, resulting in ever-growing repeated preambles #865

Open barries opened 2 days ago

barries commented 2 days ago

Every flush() results in copies of all "entries" logged so far, followed by the most recent "entry". Is this PEBKAC[1], or a bug?

type IonWriter = Writer<v1_1::Binary, File>;

pub struct Log {
    ion_writer: IonWriter,
}

impl Log {
    pub fn write_entry(
        &mut self,
        module_path:   &str,
        event_kind:    EventKind,
        write_content: impl FnOnce(&mut EntryWriter<'_>),
    ) {
        {
            let mut entry_writer = EntryWriter::new(self, module_path, event_kind);
            write_content(&mut entry_writer);
            let _ = entry_writer.ion_writer.close();
        }
        let _ = self.ion_writer.flush();
    }
}

#[rustfmt::skip]
type IonContentWriter<'a> =
    // Viewing the top-level writer as a context where values can be written...
    <<IonWriter as MakeValueWriter>
    // ...this will be the list writer type.
        ::ValueWriter<'a> as ValueWriter>::ListWriter;
        // This is indeed an unfortunately complicated way to have to refer to the type. x_x
        // This type (a list writer) implements `SequenceWriter`.

pub struct EntryWriter<'f> {
    ion_writer: IonContentWriter<'f>,
}

impl<'f> EntryWriter<'f> {
    pub fn new(
        log:         &'f mut Log,
        module_path: &str,
        event_kind:  EventKind,
    ) -> Self {
        let mut ion_writer = log.ion_writer.list_writer().expect("logger ListWriter creation failed");

        use chrono::Utc;

        let now = Utc::now().naive_utc();
        let event_timestamp = ion_rs::Timestamp::from_datetime(now, ion_rs::TimestampPrecision::Second);
        let _ = ion_writer.write(event_timestamp);
        let event_source = format!("{:?}::{module_path}", EventSource::iotaSOFT_UI);
        let _ = ion_writer.write(event_source);
        let _ = ion_writer.write(format!("{:?}", event_kind));

        Self {
            ion_writer: ion_writer,
        }
    }

    pub fn write_name(&mut self, s: &str) {
        let _ = self.ion_writer.write_symbol(s);
    }

    pub fn write_str(&mut self, s: &str) {
        let _ = self.ion_writer.write(s);
    }
    ...
}

[1] PEBKAC: Problem Exists Between Keyboard and Chair.

zslayton commented 2 days ago

Hmm, I'm not sure what's amiss here. Could you try to turn this into a failing unit test? That will make it easier for me to debug locally.