use std::time::Duration;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use crate::misc::{AuthorizationAttribute, AuthorizationAttributes, OwningApplication};
mod event_type_input;
pub use event_type_input::*;
new_type! {
#[doc=r#"Name of an EventType. The name is constrained by a regular expression.
Note: the name can encode the owner/responsible for this EventType and ideally should
follow a common pattern that makes it easy to read and understand, but this level of
structure is not enforced. For example a team name and data type can be used such as
‘acme-team.price-change’.
See also [Nakadi Manual](https://nakadi.io/manual.html#definition_EventType*name)"#]
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub struct EventTypeName(String, env="EVENT_TYPE_NAME");
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Category {
Undefined,
Data,
Business,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PartitionStrategy {
Random,
Hash,
UserDefined,
}
impl Default for PartitionStrategy {
fn default() -> Self {
PartitionStrategy::Random
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CompatibilityMode {
Compatible,
Forward,
None,
}
impl Default for CompatibilityMode {
fn default() -> Self {
CompatibilityMode::Forward
}
}
new_type! {
#[doc="Part of `PartitionKeyFields`\n"]
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct PartitionKeyField(String, env="EVENT_TYPE_PARTITION_KEY_FIELD");
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct PartitionKeyFields(Vec<PartitionKeyField>);
impl PartitionKeyFields {
pub fn new<I>(items: I) -> Self
where
I: IntoIterator,
I::Item: Into<PartitionKeyField>,
{
let items = items.into_iter().map(|it| it.into()).collect();
Self(items)
}
pub fn partition_key<T: Into<PartitionKeyField>>(mut self, v: T) -> Self {
self.push(v);
self
}
pub fn push<T: Into<PartitionKeyField>>(&mut self, v: T) {
self.0.push(v.into());
}
pub fn into_inner(self) -> Vec<PartitionKeyField> {
self.0
}
pub fn iter(&self) -> impl Iterator<Item = &PartitionKeyField> {
self.0.iter()
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut PartitionKeyField> {
self.0.iter_mut()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn len(&self) -> usize {
self.0.len()
}
}
impl<A> From<A> for PartitionKeyFields
where
A: Into<PartitionKeyField>,
{
fn from(k: A) -> Self {
Self(vec![k.into()])
}
}
impl<A, B> From<(A, B)> for PartitionKeyFields
where
A: Into<PartitionKeyField>,
B: Into<PartitionKeyField>,
{
fn from((a, b): (A, B)) -> Self {
Self(vec![a.into(), b.into()])
}
}
impl<A, B, C> From<(A, B, C)> for PartitionKeyFields
where
A: Into<PartitionKeyField>,
B: Into<PartitionKeyField>,
C: Into<PartitionKeyField>,
{
fn from((a, b, c): (A, B, C)) -> Self {
Self(vec![a.into(), b.into(), c.into()])
}
}
impl AsRef<[PartitionKeyField]> for PartitionKeyFields {
fn as_ref(&self) -> &[PartitionKeyField] {
&self.0
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CleanupPolicy {
Delete,
Compact,
}
impl Default for CleanupPolicy {
fn default() -> Self {
CleanupPolicy::Delete
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")]
pub enum SchemaType {
#[serde(rename = "json_schema")]
JsonSchema,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct EventTypeSchema {
pub version: String,
pub created_at: DateTime<Utc>,
#[serde(rename = "type")]
pub schema_type: SchemaType,
pub schema: SchemaSyntax,
}
new_type! {
#[doc=r#"
The schema as string in the syntax defined in the field type.
Failure to respect the
syntax will fail any operation on an EventType.
"#]
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct SchemaSyntax(String, env="EVENT_TYPE_SCHEMA_SYNTAX");
}
new_type! {
#[doc="Number of milliseconds that Nakadi stores events published to this event type.\n\n\
See also [Nakadi Manual](https://nakadi.io/manual.html#definition_EventTypeOptions*retention_time)"]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
pub copy struct RetentionTime(u64);
}
impl RetentionTime {
pub fn to_duration(self) -> Duration {
Duration::from_millis(self.0)
}
}
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
pub struct EventTypeOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub retention_time: Option<RetentionTime>,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct EventTypeAuthorization {
#[serde(default)]
pub admins: AuthorizationAttributes,
#[serde(default)]
pub readers: AuthorizationAttributes,
#[serde(default)]
pub writers: AuthorizationAttributes,
}
impl EventTypeAuthorization {
pub fn new<A, R, W>(admins: A, readers: R, writers: W) -> Self
where
A: Into<AuthorizationAttributes>,
R: Into<AuthorizationAttributes>,
W: Into<AuthorizationAttributes>,
{
Self {
admins: admins.into(),
readers: readers.into(),
writers: writers.into(),
}
}
pub fn admin<T: Into<AuthorizationAttribute>>(mut self, admin: T) -> Self {
self.admins.push(admin.into());
self
}
pub fn reader<T: Into<AuthorizationAttribute>>(mut self, reader: T) -> Self {
self.readers.push(reader.into());
self
}
pub fn writer<T: Into<AuthorizationAttribute>>(mut self, writer: T) -> Self {
self.writers.push(writer.into());
self
}
pub fn add_admin<T: Into<AuthorizationAttribute>>(&mut self, admin: T) {
self.admins.push(admin.into())
}
pub fn add_reader<T: Into<AuthorizationAttribute>>(&mut self, reader: T) {
self.readers.push(reader.into())
}
pub fn add_writer<T: Into<AuthorizationAttribute>>(&mut self, writer: T) {
self.writers.push(writer.into())
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub enum EventTypeAudience {
#[serde(rename = "component-internal")]
ComponentInternal,
#[serde(rename = "business-unit-internal")]
BusinessUnitInternal,
#[serde(rename = "company-internal")]
CompanyInternal,
#[serde(rename = "external-partner")]
ExternalPartner,
#[serde(rename = "external-public")]
ExternalPublic,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
#[serde(rename_all = "snake_case")]
pub enum EnrichmentStrategy {
MetadataEnrichment,
}
impl Default for EnrichmentStrategy {
fn default() -> Self {
EnrichmentStrategy::MetadataEnrichment
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub struct EventTypeStatistics {
pub messages_per_minute: u64,
pub message_size: u64,
pub read_parallelism: u64,
pub write_parallelism: u64,
}
impl EventTypeStatistics {
pub fn new(
messages_per_minute: u64,
message_size: u64,
read_parallelism: u64,
write_parallelism: u64,
) -> Self {
Self {
messages_per_minute,
message_size,
read_parallelism,
write_parallelism,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EventType {
pub name: EventTypeName,
pub owning_application: Option<OwningApplication>,
pub category: Category,
#[serde(default)]
pub enrichment_strategies: Vec<EnrichmentStrategy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub partition_strategy: Option<PartitionStrategy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub compatibility_mode: Option<CompatibilityMode>,
pub schema: EventTypeSchema,
#[serde(default)]
pub partition_key_fields: PartitionKeyFields,
#[serde(skip_serializing_if = "Option::is_none")]
pub cleanup_policy: Option<CleanupPolicy>,
#[serde(skip_serializing_if = "Option::is_none")]
pub default_statistic: Option<EventTypeStatistics>,
#[serde(default)]
pub options: EventTypeOptions,
#[serde(skip_serializing_if = "Option::is_none")]
pub authorization: Option<EventTypeAuthorization>,
pub audience: Option<EventTypeAudience>,
#[serde(default)]
pub ordering_key_fields: Vec<String>,
#[serde(default)]
pub ordering_instance_ids: Vec<String>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}