1use std::convert::AsRef;
3use std::fmt;
4use std::time::Duration;
5
6use chrono::{DateTime, Utc};
7use serde::{Deserialize, Deserializer, Serialize};
8use uuid::Uuid;
9
10use crate::misc::{AuthorizationAttribute, AuthorizationAttributes, OwningApplication};
11use crate::partition::{Cursor, CursorOffset, PartitionId};
12use crate::Error;
13
14mod subscription_input;
15pub use crate::event_type::EventTypeName;
16pub use subscription_input::*;
17
18pub type SubscriptionCursorWithoutToken = EventTypeCursor;
25
26new_type! {
27 #[doc=r#"Id of subscription that was created.
28
29Is generated by Nakadi, should not be specified when creating
30subscription.
31
32See also [Nakadi Manual](https://nakadi.io/manual.html#definition_Subscription)"#]
33 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
34 pub copy struct SubscriptionId(Uuid, env="SUBSCRIPTION_ID");
35}
36
37impl SubscriptionId {
38 pub fn random() -> Self {
39 Self(Uuid::new_v4())
40 }
41}
42
43new_type! {
44 #[doc=r#"The id of this stream generated by Nakadi.
45
46Must be used for committing events that were read by client from this stream.
47
48See also [Nakadi Manual](https://nakadi.io/manual.html#/subscriptions/subscription_id/events_get)"#]
49 #[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
50 pub copy struct StreamId(Uuid);
51}
52
53impl StreamId {
54 pub fn random() -> Self {
55 Self(Uuid::new_v4())
56 }
57}
58
59pub trait EventTypePartitionLike {
63 fn event_type(&self) -> &EventTypeName;
64 fn partition(&self) -> &PartitionId;
65}
66
67#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
71pub struct EventTypePartition {
72 pub event_type: EventTypeName,
73 pub partition: PartitionId,
74}
75
76impl EventTypePartition {
77 pub fn new<E: Into<EventTypeName>, P: Into<PartitionId>>(event_type: E, partition: P) -> Self {
78 Self {
79 event_type: event_type.into(),
80 partition: partition.into(),
81 }
82 }
83
84 pub fn split(self) -> (EventTypeName, PartitionId) {
86 (self.event_type, self.partition)
87 }
88
89 pub fn event_type(&self) -> &EventTypeName {
91 &self.event_type
92 }
93
94 pub fn partition(&self) -> &PartitionId {
96 &self.partition
97 }
98}
99
100impl fmt::Display for EventTypePartition {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 write!(
103 f,
104 "[event_type={};partition={}]",
105 self.event_type, self.partition
106 )?;
107 Ok(())
108 }
109}
110
111impl EventTypePartitionLike for EventTypePartition {
112 fn event_type(&self) -> &EventTypeName {
113 &self.event_type
114 }
115
116 fn partition(&self) -> &PartitionId {
117 &self.partition
118 }
119}
120
121impl From<SubscriptionCursor> for EventTypePartition {
122 fn from(v: SubscriptionCursor) -> Self {
123 v.into_event_type_partition()
124 }
125}
126
127impl From<EventTypeCursor> for EventTypePartition {
128 fn from(v: EventTypeCursor) -> Self {
129 Self {
130 event_type: v.event_type,
131 partition: v.cursor.partition,
132 }
133 }
134}
135
136#[derive(Debug, Clone, Default, Serialize, Deserialize)]
140pub struct EventTypeNames(Vec<EventTypeName>);
141
142impl EventTypeNames {
143 pub fn new<T: Into<Vec<EventTypeName>>>(event_types: T) -> Self {
144 Self(event_types.into())
145 }
146
147 pub fn event_type_name<T: Into<EventTypeName>>(mut self, v: T) -> Self {
148 self.0.push(v.into());
149 self
150 }
151
152 pub fn into_inner(self) -> Vec<EventTypeName> {
154 self.0
155 }
156
157 pub fn len(&self) -> usize {
158 self.0.len()
159 }
160
161 pub fn is_empty(&self) -> bool {
162 self.0.is_empty()
163 }
164
165 pub fn push<T: Into<EventTypeName>>(&mut self, event_type: T) {
166 self.0.push(event_type.into())
167 }
168}
169
170impl AsRef<[EventTypeName]> for EventTypeNames {
171 fn as_ref(&self) -> &[EventTypeName] {
172 &self.0
173 }
174}
175
176new_type! {
177#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
182 pub struct ConsumerGroup(String, env="CONSUMER_GROUP");
183}
184
185#[derive(Debug, Clone, Serialize, Deserialize)]
194pub struct SubscriptionEventTypeStatus {
195 pub event_type: EventTypeName,
196 pub partitions: Vec<SubscriptionPartitionStatus>,
197}
198
199#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
203pub struct SubscriptionPartitionStatus {
204 pub partition: PartitionId,
206 pub state: PartitionState,
208 pub stream_id: Option<StreamId>,
210 pub assignment_type: Option<PartitionAssignmentType>,
211}
212
213#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
217pub enum PartitionState {
218 #[serde(rename = "unassigned")]
220 Unassigned,
221 #[serde(rename = "reassigned")]
223 Reassigned,
224 #[serde(rename = "assigned")]
226 Assigned,
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
233pub enum PartitionAssignmentType {
234 #[serde(rename = "direct")]
236 Direct,
237 #[serde(rename = "auto")]
240 Auto,
241}
242
243#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
252pub struct SubscriptionAuthorization {
253 pub admins: AuthorizationAttributes,
254 pub readers: AuthorizationAttributes,
255}
256
257impl SubscriptionAuthorization {
258 pub fn new<A, R>(admins: A, readers: R) -> Self
259 where
260 A: Into<AuthorizationAttributes>,
261 R: Into<AuthorizationAttributes>,
262 {
263 Self {
264 admins: admins.into(),
265 readers: readers.into(),
266 }
267 }
268
269 pub fn admin<T: Into<AuthorizationAttribute>>(mut self, admin: T) -> Self {
270 self.admins.push(admin.into());
271 self
272 }
273 pub fn reader<T: Into<AuthorizationAttribute>>(mut self, reader: T) -> Self {
274 self.readers.push(reader.into());
275 self
276 }
277
278 pub fn add_admin<T: Into<AuthorizationAttribute>>(&mut self, admin: T) {
279 self.admins.push(admin.into())
280 }
281 pub fn add_reader<T: Into<AuthorizationAttribute>>(&mut self, reader: T) {
282 self.readers.push(reader.into())
283 }
284}
285
286#[derive(Debug, Clone, Deserialize)]
295pub struct Subscription {
296 pub id: SubscriptionId,
297 pub owning_application: OwningApplication,
298 pub event_types: EventTypeNames,
299 #[serde(skip_serializing_if = "Option::is_none")]
300 pub consumer_group: Option<ConsumerGroup>,
301 pub created_at: DateTime<Utc>,
302 pub updated_at: DateTime<Utc>,
303}
304
305#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
314pub struct EventTypeCursor {
315 #[serde(flatten)]
316 pub cursor: Cursor,
317 pub event_type: EventTypeName,
319}
320
321impl EventTypePartitionLike for EventTypeCursor {
322 fn event_type(&self) -> &EventTypeName {
323 &self.event_type
324 }
325
326 fn partition(&self) -> &PartitionId {
327 &self.cursor.partition
328 }
329}
330
331impl From<SubscriptionCursor> for EventTypeCursor {
332 fn from(c: SubscriptionCursor) -> Self {
333 c.into_event_type_cursor()
334 }
335}
336
337impl<'de> Deserialize<'de> for EventTypeCursor {
338 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
339 where
340 D: Deserializer<'de>,
341 {
342 #[derive(Deserialize)]
343 struct A {
344 #[serde(flatten)]
345 cursor: Cursor,
346 event_type: EventTypeName,
347 }
348
349 #[derive(Deserialize)]
350 struct B {
351 cursor: Cursor,
352 event_type: EventTypeName,
353 }
354
355 #[derive(Deserialize)]
356 #[serde(untagged)]
357 enum Variant {
358 A(A),
359 B(B),
360 }
361
362 let variant = Variant::deserialize(deserializer)?;
363
364 match variant {
365 Variant::A(x) => Ok(EventTypeCursor {
366 cursor: x.cursor,
367 event_type: x.event_type,
368 }),
369 Variant::B(x) => Ok(EventTypeCursor {
370 cursor: x.cursor,
371 event_type: x.event_type,
372 }),
373 }
374 }
375}
376
377#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
379pub struct CursorToken(String);
380
381impl CursorToken {
382 pub fn new<T: Into<String>>(token: T) -> Self {
383 Self(token.into())
384 }
385}
386
387#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
392pub struct SubscriptionCursor {
393 #[serde(flatten)]
394 pub cursor: Cursor,
395 pub event_type: EventTypeName,
397 pub cursor_token: CursorToken,
399}
400
401impl SubscriptionCursor {
402 pub fn into_event_type_cursor(self) -> EventTypeCursor {
403 EventTypeCursor {
404 cursor: self.cursor,
405 event_type: self.event_type,
406 }
407 }
408
409 pub fn into_event_type_cursor_begin(self) -> EventTypeCursor {
411 EventTypeCursor {
412 cursor: Cursor {
413 partition: self.cursor.partition,
414 offset: CursorOffset::Begin,
415 },
416 event_type: self.event_type,
417 }
418 }
419
420 pub fn into_event_type_partition(self) -> EventTypePartition {
421 EventTypePartition {
422 event_type: self.event_type,
423 partition: self.cursor.partition,
424 }
425 }
426
427 pub fn to_event_type_partition(&self) -> EventTypePartition {
428 EventTypePartition {
429 event_type: self.event_type.clone(),
430 partition: self.cursor.partition.clone(),
431 }
432 }
433}
434
435impl EventTypePartitionLike for SubscriptionCursor {
436 fn event_type(&self) -> &EventTypeName {
437 &self.event_type
438 }
439
440 fn partition(&self) -> &PartitionId {
441 &self.cursor.partition
442 }
443}
444
445#[derive(Debug, Default, Clone, Serialize, Deserialize)]
449pub struct CursorCommitResults {
450 #[serde(rename = "items")]
451 pub commit_results: Vec<CursorCommitResult>,
452}
453
454impl CursorCommitResults {
455 pub fn all_committed(&self) -> bool {
456 self.commit_results
457 .iter()
458 .all(|r| r.result == CommitResult::Committed)
459 }
460
461 pub fn iter_committed_cursors(&self) -> impl Iterator<Item = &SubscriptionCursor> {
462 self.commit_results
463 .iter()
464 .filter(|r| r.is_committed())
465 .map(|r| &r.cursor)
466 }
467
468 pub fn into_iter_committed_cursors(self) -> impl Iterator<Item = SubscriptionCursor> {
469 self.commit_results
470 .into_iter()
471 .filter(|r| r.is_committed())
472 .map(|r| r.cursor)
473 }
474
475 pub fn iter_outdated_cursors(&self) -> impl Iterator<Item = &SubscriptionCursor> {
476 self.commit_results
477 .iter()
478 .filter(|r| r.is_outdated())
479 .map(|r| &r.cursor)
480 }
481
482 pub fn into_iter_outdated_cursors(self) -> impl Iterator<Item = SubscriptionCursor> {
483 self.commit_results
484 .into_iter()
485 .filter(|r| r.is_outdated())
486 .map(|r| r.cursor)
487 }
488
489 pub fn into_inner(self) -> Vec<CursorCommitResult> {
490 self.commit_results
491 }
492}
493
494impl From<CursorCommitResults> for Vec<CursorCommitResult> {
495 fn from(v: CursorCommitResults) -> Self {
496 v.into_inner()
497 }
498}
499
500#[derive(Debug, Clone, Serialize, Deserialize)]
504pub struct CursorCommitResult {
505 pub cursor: SubscriptionCursor,
506 pub result: CommitResult,
507}
508
509impl CursorCommitResult {
510 pub fn is_committed(&self) -> bool {
511 self.result == CommitResult::Committed
512 }
513
514 pub fn is_outdated(&self) -> bool {
515 self.result == CommitResult::Outdated
516 }
517}
518
519#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
523#[serde(rename_all = "snake_case")]
524pub enum CommitResult {
525 Committed,
527 Outdated,
530}
531
532#[derive(Debug, Clone, Serialize, Deserialize)]
533pub struct SubscriptionStats {
534 #[serde(rename = "items")]
535 pub event_type_stats: Vec<SubscriptionEventTypeStats>,
536}
537
538impl SubscriptionStats {
539 pub fn unconsumed_events(&self) -> Option<usize> {
540 let mut is_sum = false;
541 let sum = self
542 .event_type_stats
543 .iter()
544 .filter_map(|set_stats| {
545 if set_stats.unconsumed_events().is_some() {
546 is_sum = true;
547 }
548
549 set_stats.unconsumed_events()
550 })
551 .sum();
552
553 if is_sum {
554 Some(sum)
555 } else {
556 None
557 }
558 }
559
560 pub fn unconsumed_stream_events(&self, for_stream: StreamId) -> Option<usize> {
563 let mut is_sum = false;
564 let sum = self
565 .event_type_stats
566 .iter()
567 .filter_map(|event_type_stats| {
568 if let Some(unconsumend) = event_type_stats.unconsumed_stream_events(for_stream) {
569 is_sum = true;
570 Some(unconsumend)
571 } else {
572 None
573 }
574 })
575 .sum();
576
577 if is_sum {
578 Some(sum)
579 } else {
580 None
581 }
582 }
583
584 pub fn all_events_consumed(&self) -> bool {
585 self.unconsumed_events() == Some(0)
586 }
587}
588
589#[derive(Debug, Clone, Serialize, Deserialize)]
593pub struct SubscriptionEventTypeStats {
594 pub event_type: EventTypeName,
595 #[serde(default)]
596 pub partitions: Vec<SubscriptionEventTypePartitionStats>,
597}
598
599impl SubscriptionEventTypeStats {
600 pub fn unconsumed_events(&self) -> Option<usize> {
602 let mut is_sum = false;
603 let sum = self
604 .partitions
605 .iter()
606 .filter_map(|p| {
607 if p.unconsumed_events.is_some() {
608 is_sum = true;
609 }
610
611 p.unconsumed_events
612 })
613 .sum();
614
615 if is_sum {
616 Some(sum)
617 } else {
618 None
619 }
620 }
621
622 pub fn all_events_consumed(&self) -> bool {
625 self.unconsumed_events() == Some(0)
626 }
627
628 pub fn unconsumed_stream_events(&self, for_stream: StreamId) -> Option<usize> {
631 let mut is_sum = false;
632 let sum = self
633 .partitions
634 .iter()
635 .filter_map(|p| {
636 p.stream_id.and_then(|s| {
637 if s == for_stream {
638 if p.unconsumed_events.is_some() {
639 is_sum = true;
640 }
641 p.unconsumed_events
642 } else {
643 None
644 }
645 })
646 })
647 .sum();
648
649 if is_sum {
650 Some(sum)
651 } else {
652 None
653 }
654 }
655}
656
657#[derive(Debug, Clone, Serialize, Deserialize)]
661pub struct SubscriptionEventTypePartitionStats {
662 partition: PartitionId,
663 #[serde(skip_serializing_if = "Option::is_none")]
670 unconsumed_events: Option<usize>,
671 #[serde(skip_serializing_if = "Option::is_none")]
674 consumer_lag_seconds: Option<u64>,
675 #[serde(deserialize_with = "crate::deserialize_empty_string_is_none")]
677 #[serde(skip_serializing_if = "Option::is_none")]
678 stream_id: Option<StreamId>,
679 #[serde(skip_serializing_if = "Option::is_none")]
680 assignment_type: Option<String>,
684 state: SubscriptionPartitionState,
690}
691
692#[derive(Debug, Clone, Serialize, Deserialize)]
696#[serde(rename_all = "snake_case")]
697pub enum SubscriptionPartitionState {
698 Assigned,
700 Unassigned,
702 Reassigning,
704}
705
706#[derive(Debug, Clone, Serialize, Deserialize)]
708#[serde(rename_all = "snake_case")]
709pub enum SubscriptionPartitionAssignmentType {
710 Direct,
712 Auto,
715}
716
717#[cfg(test)]
718mod test {
719 use super::*;
720 use crate::partition::CursorOffset;
721
722 use serde_json::{self, json};
723
724 #[test]
725 fn subscription_cursor_without_token() {
726 let json = json!({
727 "event_type": "the event",
728 "partition": "the partition",
729 "offset": "12345",
730 });
731
732 let sample = EventTypeCursor {
733 event_type: EventTypeName::new("the event"),
734 cursor: Cursor {
735 partition: PartitionId::new("the partition"),
736 offset: CursorOffset::new("12345"),
737 },
738 };
739
740 assert_eq!(
741 serde_json::to_value(sample.clone()).unwrap(),
742 json,
743 "serialize"
744 );
745 assert_eq!(
746 serde_json::from_value::<EventTypeCursor>(json).unwrap(),
747 sample,
748 "deserialize"
749 );
750 }
751
752 #[test]
753 fn subscription_cursor() {
754 let json = json!({
755 "event_type": "the event",
756 "partition": "the partition",
757 "offset": "12345",
758 "cursor_token": "abcdef",
759 });
760
761 let sample = SubscriptionCursor {
762 event_type: EventTypeName::new("the event"),
763 cursor_token: CursorToken::new("abcdef"),
764 cursor: Cursor {
765 partition: PartitionId::new("the partition"),
766 offset: CursorOffset::new("12345"),
767 },
768 };
769
770 assert_eq!(
771 serde_json::to_value(sample.clone()).unwrap(),
772 json,
773 "serialize"
774 );
775 assert_eq!(
776 serde_json::from_value::<SubscriptionCursor>(json).unwrap(),
777 sample,
778 "deserialize"
779 );
780 }
781}
782
783#[derive(Debug, Default, Clone, Serialize, Deserialize)]
800pub struct StreamParameters {
801 #[serde(skip_serializing_if = "Vec::is_empty")]
804 pub partitions: Vec<EventTypePartition>,
805 #[serde(skip_serializing_if = "Option::is_none")]
808 pub max_uncommitted_events: Option<StreamMaxUncommittedEvents>,
809 #[serde(skip_serializing_if = "Option::is_none")]
811 pub batch_limit: Option<StreamBatchLimit>,
812 #[serde(skip_serializing_if = "Option::is_none")]
815 pub stream_limit: Option<StreamLimit>,
816 #[serde(skip_serializing_if = "Option::is_none")]
818 #[serde(rename = "batch_flush_timeout")]
819 pub batch_flush_timeout_secs: Option<StreamBatchFlushTimeoutSecs>,
820 #[serde(skip_serializing_if = "Option::is_none")]
825 #[serde(rename = "batch_timespan")]
826 pub batch_timespan_secs: Option<StreamBatchTimespanSecs>,
827 #[serde(skip_serializing_if = "Option::is_none")]
831 #[serde(rename = "stream_timeout")]
832 pub stream_timeout_secs: Option<StreamTimeoutSecs>,
833 #[serde(skip_serializing_if = "Option::is_none")]
838 #[serde(rename = "commit_timeout")]
839 pub commit_timeout_secs: Option<StreamCommitTimeoutSecs>,
840}
841
842impl StreamParameters {
843 pub fn from_env() -> Result<Self, Error> {
845 let mut me = Self::default();
846 me.fill_from_env()?;
847 Ok(me)
848 }
849
850 pub fn from_env_prefixed<T: AsRef<str>>(prefix: T) -> Result<Self, Error> {
854 let mut me = Self::default();
855 me.fill_from_env_prefixed(prefix)?;
856 Ok(me)
857 }
858
859 pub fn from_env_type_names() -> Result<Self, Error> {
861 let mut me = Self::default();
862 me.fill_from_env_type_names()?;
863 Ok(me)
864 }
865
866 pub fn fill_from_env(&mut self) -> Result<(), Error> {
868 self.fill_from_env_prefixed(crate::helpers::NAKADION_PREFIX)
869 }
870
871 pub fn fill_from_env_type_names(&mut self) -> Result<(), Error> {
873 self.fill_from_env_prefixed("")
874 }
875
876 pub fn fill_from_env_prefixed<T: AsRef<str>>(&mut self, prefix: T) -> Result<(), Error> {
880 if self.max_uncommitted_events.is_none() {
881 self.max_uncommitted_events =
882 StreamMaxUncommittedEvents::try_from_env_prefixed(prefix.as_ref())?;
883 }
884 if self.batch_limit.is_none() {
885 self.batch_limit = StreamBatchLimit::try_from_env_prefixed(prefix.as_ref())?;
886 }
887 if self.stream_limit.is_none() {
888 self.stream_limit = StreamLimit::try_from_env_prefixed(prefix.as_ref())?;
889 }
890 if self.batch_flush_timeout_secs.is_none() {
891 self.batch_flush_timeout_secs =
892 StreamBatchFlushTimeoutSecs::try_from_env_prefixed(prefix.as_ref())?;
893 }
894 if self.batch_timespan_secs.is_none() {
895 self.batch_timespan_secs =
896 StreamBatchTimespanSecs::try_from_env_prefixed(prefix.as_ref())?;
897 }
898 if self.stream_timeout_secs.is_none() {
899 self.stream_timeout_secs = StreamTimeoutSecs::try_from_env_prefixed(prefix.as_ref())?;
900 }
901 if self.commit_timeout_secs.is_none() {
902 self.commit_timeout_secs =
903 StreamCommitTimeoutSecs::try_from_env_prefixed(prefix.as_ref())?;
904 }
905
906 Ok(())
907 }
908
909 pub fn apply_defaults(&mut self) {
910 if self.max_uncommitted_events.is_none() {
911 self.max_uncommitted_events = Some(StreamMaxUncommittedEvents::default());
912 }
913 if self.batch_limit.is_none() {
914 self.batch_limit = Some(StreamBatchLimit::default());
915 }
916 if self.stream_limit.is_none() {
917 self.stream_limit = Some(StreamLimit::default());
918 }
919 if self.batch_flush_timeout_secs.is_none() {
920 self.batch_flush_timeout_secs = Some(StreamBatchFlushTimeoutSecs::default());
921 }
922 if self.batch_timespan_secs.is_none() {
923 self.batch_timespan_secs = Some(StreamBatchTimespanSecs::default());
924 }
925 if self.stream_timeout_secs.is_none() {
926 self.stream_timeout_secs = Some(StreamTimeoutSecs::default());
927 }
928 if self.commit_timeout_secs.is_none() {
929 self.commit_timeout_secs = Some(StreamCommitTimeoutSecs::default());
930 }
931 }
932
933 pub fn partitions(mut self, partitions: Vec<EventTypePartition>) -> Self {
936 self.partitions = partitions;
937 self
938 }
939 pub fn max_uncommitted_events<T: Into<StreamMaxUncommittedEvents>>(mut self, value: T) -> Self {
944 self.max_uncommitted_events = Some(value.into());
945 self
946 }
947 pub fn batch_limit<T: Into<StreamBatchLimit>>(mut self, value: T) -> Self {
949 self.batch_limit = Some(value.into());
950 self
951 }
952 pub fn stream_limit<T: Into<StreamLimit>>(mut self, value: T) -> Self {
955 self.stream_limit = Some(value.into());
956 self
957 }
958 pub fn batch_flush_timeout_secs<T: Into<StreamBatchFlushTimeoutSecs>>(
960 mut self,
961 value: T,
962 ) -> Self {
963 self.batch_flush_timeout_secs = Some(value.into());
964 self
965 }
966 pub fn batch_timespan_secs<T: Into<StreamBatchTimespanSecs>>(mut self, value: T) -> Self {
973 self.batch_timespan_secs = Some(value.into());
974 self
975 }
976 pub fn stream_timeout_secs<T: Into<StreamTimeoutSecs>>(mut self, value: T) -> Self {
978 self.stream_timeout_secs = Some(value.into());
979 self
980 }
981 pub fn commit_timeout_secs<T: Into<StreamCommitTimeoutSecs>>(mut self, value: T) -> Self {
987 self.commit_timeout_secs = Some(value.into());
988 self
989 }
990
991 pub fn effective_commit_timeout_secs(&self) -> u32 {
993 self.commit_timeout_secs
994 .map(|s| s.into_inner())
995 .unwrap_or(60)
996 }
997
998 pub fn effective_max_uncommitted_events(&self) -> u32 {
1000 self.max_uncommitted_events
1001 .map(|s| s.into_inner())
1002 .unwrap_or(10)
1003 }
1004
1005 pub fn effective_batch_limit(&self) -> u32 {
1007 self.batch_limit.map(|s| s.into_inner()).unwrap_or(1)
1008 }
1009}
1010
1011new_type! {
1012 #[doc="The maximum number of uncommitted events that Nakadi will stream before pausing the stream.\n"]
1013 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1014 pub copy struct StreamMaxUncommittedEvents(u32, env="STREAM_MAX_UNCOMMITTED_EVENTS");
1015}
1016impl Default for StreamMaxUncommittedEvents {
1017 fn default() -> Self {
1018 10.into()
1019 }
1020}
1021new_type! {
1022 #[doc="Maximum number of Events in each chunk (and therefore per partition) of the stream.\n"]
1023 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1024 pub copy struct StreamBatchLimit(u32, env="STREAM_BATCH_LIMIT");
1025}
1026impl Default for StreamBatchLimit {
1027 fn default() -> Self {
1028 1.into()
1029 }
1030}
1031new_type! {
1032 #[doc="Maximum number of Events in this stream \
1033 (over all partitions being streamed in this connection).\n\n\
1034 0 means infinite"]
1035 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1036 pub copy struct StreamLimit(u32, env="STREAM_LIMIT");
1037}
1038impl Default for StreamLimit {
1039 fn default() -> Self {
1040 0.into()
1041 }
1042}
1043new_type! {
1044 #[doc="Maximum time in seconds to wait for the flushing of each chunk (per partition).\n"]
1045 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1046 pub secs struct StreamBatchFlushTimeoutSecs(u32, env="STREAM_BATCH_FLUSH_TIMEOUT_SECS");
1047}
1048impl Default for StreamBatchFlushTimeoutSecs {
1049 fn default() -> Self {
1050 30.into()
1051 }
1052}
1053new_type! {
1054 #[doc="Useful for batching events based on their received_at timestamp.\n"]
1055 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1056 pub secs struct StreamBatchTimespanSecs(u32, env="STREAM_BATCH_TIMESPAN_SECS");
1057}
1058impl Default for StreamBatchTimespanSecs {
1059 fn default() -> Self {
1060 0.into()
1061 }
1062}
1063new_type! {
1064 #[doc="Maximum time in seconds a stream will live before connection is closed by the server.\n"]
1065 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1066 pub secs struct StreamTimeoutSecs(u32, env="STREAM_TIMEOUT_SECS");
1067}
1068impl Default for StreamTimeoutSecs {
1069 fn default() -> Self {
1070 0.into()
1071 }
1072}
1073new_type! {
1074 #[doc="Maximum amount of seconds that Nakadi will be waiting for commit after sending a batch to a client.\n"]
1075 #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1076 pub secs struct StreamCommitTimeoutSecs(u32, env="STREAM_COMMIT_TIMEOUT_SECS");
1077}
1078impl Default for StreamCommitTimeoutSecs {
1079 fn default() -> Self {
1080 60.into()
1081 }
1082}