1use std::collections::BTreeMap;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum Owner {
8 Salesforce,
10 Postgres,
12 Shared,
14}
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
18pub enum ConflictPolicy {
19 FieldOwnership,
21 #[default]
23 ManualReview,
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct LaneThresholds {
29 rest_max_batch_size: usize,
30 bulk_min_batch_size: usize,
31}
32
33impl LaneThresholds {
34 #[must_use]
36 pub const fn rest_max_batch_size(&self) -> usize {
37 self.rest_max_batch_size
38 }
39
40 #[must_use]
42 pub const fn bulk_min_batch_size(&self) -> usize {
43 self.bulk_min_batch_size
44 }
45}
46
47impl Default for LaneThresholds {
48 fn default() -> Self {
49 Self {
50 rest_max_batch_size: 25,
51 bulk_min_batch_size: 500,
52 }
53 }
54}
55
56#[derive(Debug, Clone, PartialEq, Eq)]
58pub struct ObjectSync {
59 object_name: String,
60 external_id_field: Option<String>,
61 conflict_policy: ConflictPolicy,
62 lane_thresholds: LaneThresholds,
63 field_ownership: BTreeMap<String, Owner>,
64}
65
66impl ObjectSync {
67 #[must_use]
69 pub fn new(object_name: impl Into<String>) -> Self {
70 Self {
71 object_name: object_name.into(),
72 external_id_field: None,
73 conflict_policy: ConflictPolicy::default(),
74 lane_thresholds: LaneThresholds::default(),
75 field_ownership: BTreeMap::new(),
76 }
77 }
78
79 #[must_use]
81 pub fn external_id(mut self, external_id_field: impl Into<String>) -> Self {
82 self.external_id_field = Some(external_id_field.into());
83 self
84 }
85
86 #[must_use]
88 pub fn field_owner(mut self, field_name: impl Into<String>, owner: Owner) -> Self {
89 self.field_ownership.insert(field_name.into(), owner);
90 self
91 }
92
93 #[must_use]
95 pub fn object_name(&self) -> &str {
96 &self.object_name
97 }
98
99 #[must_use]
101 pub fn external_id_field(&self) -> Option<&str> {
102 self.external_id_field.as_deref()
103 }
104
105 #[must_use]
107 pub const fn conflict_policy(&self) -> &ConflictPolicy {
108 &self.conflict_policy
109 }
110
111 #[must_use]
113 pub const fn lane_thresholds(&self) -> &LaneThresholds {
114 &self.lane_thresholds
115 }
116
117 #[must_use]
119 pub fn field_owner_for(&self, field_name: &str) -> Option<Owner> {
120 self.field_ownership.get(field_name).copied()
121 }
122
123 #[must_use]
125 pub const fn field_ownership(&self) -> &BTreeMap<String, Owner> {
126 &self.field_ownership
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::{ObjectSync, Owner};
133
134 #[test]
135 fn object_sync_external_id_builder_stores_config() {
136 let config = ObjectSync::new("Account").external_id("External_Id__c");
137
138 assert_eq!(config.object_name(), "Account");
139 assert_eq!(config.external_id_field(), Some("External_Id__c"));
140 }
141
142 #[test]
143 fn object_sync_field_owner_builder_stores_rules() {
144 let config = ObjectSync::new("Account").field_owner("Name", Owner::Postgres);
145
146 assert_eq!(config.field_owner_for("Name"), Some(Owner::Postgres));
147 assert_eq!(config.field_ownership().len(), 1);
148 }
149}