pub struct SinkRecord {
pub data: Value,
pub schema_id: String,
pub source_url: String,
pub fetched_at: DateTime<Utc>,
pub metadata: HashMap<String, String>,
}Expand description
A single structured record to be published through a DataSinkPort.
§Example
use stygian_graph::ports::data_sink::SinkRecord;
use serde_json::json;
let record = SinkRecord::new(
"product-v1",
"https://shop.example.com/items/42",
json!({ "sku": "ABC-42", "price": 9.99 }),
);
assert_eq!(record.schema_id, "product-v1");Fields§
§data: ValueThe payload to publish. Any JSON value is accepted.
schema_id: StringIdentifies the schema or data-contract version this record conforms to. Sinks may use this for routing, validation, or schema-registry lookups.
source_url: StringThe canonical URL the record was scraped from. Used for provenance and
deduplication. Stored as a String to avoid a url crate dependency
in the port layer.
fetched_at: DateTime<Utc>T108 mandatory — the wall-clock instant at which the source
was fetched, as observed by the transport (HTTP Date header
for HTTP-sourced records, browser Date.now() for
browser-sourced records).
This field is required. Adapters and consumers cannot construct
a SinkRecord without supplying it — use
SinkRecord::with_fetched_at or
SinkRecord::fetched_at_or_default to provide it.
The fetched_at value should be the transport-supplied
timestamp, not Utc::now() computed post-extraction. The
guard test in tests/sink_invariants.rs asserts every
adapter uses a transport-level source.
metadata: HashMap<String, String>Arbitrary string key-value metadata (content-type, run-id, tenant, …).
Implementations§
Source§impl SinkRecord
impl SinkRecord
Sourcepub fn new(
schema_id: impl Into<String>,
source_url: impl Into<String>,
data: Value,
) -> Self
pub fn new( schema_id: impl Into<String>, source_url: impl Into<String>, data: Value, ) -> Self
Construct a new SinkRecord with empty metadata and
fetched_at = chrono::Utc::now() as the fallback for
callers that don’t have a transport-level timestamp.
Prefer SinkRecord::with_fetched_at — using
Utc::now() here means the record carries the time of
construction, not the time of the upstream fetch.
Sourcepub fn with_fetched_at(
schema_id: impl Into<String>,
source_url: impl Into<String>,
data: Value,
fetched_at: DateTime<Utc>,
) -> Self
pub fn with_fetched_at( schema_id: impl Into<String>, source_url: impl Into<String>, data: Value, fetched_at: DateTime<Utc>, ) -> Self
Construct a SinkRecord with an explicit fetched_at
timestamp. This is the preferred constructor — the
caller is required to supply a transport-level timestamp.
§Example
use stygian_graph::ports::data_sink::SinkRecord;
use chrono::{TimeZone, Utc};
let fetched_at = Utc.with_ymd_and_hms(2026, 8, 22, 12, 0, 0).unwrap();
let r = SinkRecord::with_fetched_at(
"schema-v1",
"https://example.com/page",
serde_json::Value::Null,
fetched_at,
);
assert_eq!(r.fetched_at, fetched_at);Sourcepub fn fetched_at_or_default(
schema_id: impl Into<String>,
source_url: impl Into<String>,
data: Value,
default_fetched_at: DateTime<Utc>,
) -> Self
pub fn fetched_at_or_default( schema_id: impl Into<String>, source_url: impl Into<String>, data: Value, default_fetched_at: DateTime<Utc>, ) -> Self
Construct a SinkRecord using default_fetched_at only
when the caller does not have a transport-level timestamp.
The default_fetched_at value is recorded verbatim — use
chrono::Utc::now for a “now” fallback, or pass an HTTP
Date header value parsed into a chrono::DateTime<Utc>.
Sourcepub fn with_meta(self, key: impl Into<String>, value: impl Into<String>) -> Self
pub fn with_meta(self, key: impl Into<String>, value: impl Into<String>) -> Self
Attach a metadata entry and return self for builder-style use.
§Example
use stygian_graph::ports::data_sink::SinkRecord;
use chrono::Utc;
let r = SinkRecord::new("s", "https://x.com", serde_json::Value::Null)
.with_meta("run_id", "abc123");
assert_eq!(r.metadata["run_id"], "abc123");Trait Implementations§
Source§impl Clone for SinkRecord
impl Clone for SinkRecord
Source§fn clone(&self) -> SinkRecord
fn clone(&self) -> SinkRecord
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for SinkRecord
impl Debug for SinkRecord
Source§impl<'de> Deserialize<'de> for SinkRecord
impl<'de> Deserialize<'de> for SinkRecord
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for SinkRecord
impl RefUnwindSafe for SinkRecord
impl Send for SinkRecord
impl Sync for SinkRecord
impl Unpin for SinkRecord
impl UnsafeUnpin for SinkRecord
impl UnwindSafe for SinkRecord
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling [Attribute] value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi [Quirk] value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the [Condition] value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);