Skip to content

Commit 451624c

Browse files
committed
Fixes
1 parent 2921aff commit 451624c

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

MY_NO_SQL_ENTITY_DESIGN_PATTERNS.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
- Prefer stable identifiers (ids, symbols, timestamps encoded consistently).
144144
- TimeStamp:
145145
- Auto-managed; used by server for last-write tracking and sync ordering.
146+
- **Important**: When creating a new entity instance, do not set the current timestamp manually. The server will automatically set the timestamp when the entity is written. Always initialize `time_stamp` with `Default::default()`.
146147
- Expires (TTL):
147148
- Use for session-like or cache-like data; choose UTC epoch milliseconds.
148149

@@ -179,6 +180,89 @@
179180
}
180181
```
181182

183+
### Best practices: timestamp initialization
184+
- **Never set the current timestamp manually** when creating a `MyNoSqlEntity` instance. The server automatically assigns the timestamp when the entity is written or updated.
185+
- Always initialize `time_stamp` with `Default::default()` in constructors, `Default` implementations, or when manually creating entity instances.
186+
- Example - Complete initialization patterns:
187+
```rust
188+
use my_no_sql_macros::my_no_sql_entity;
189+
use serde::{Deserialize, Serialize};
190+
191+
#[my_no_sql_entity("user-profiles")]
192+
#[derive(Serialize, Deserialize, Debug, Clone)]
193+
pub struct UserProfileEntity {
194+
pub user_name: String,
195+
pub email: String,
196+
pub age: u32,
197+
}
198+
199+
impl UserProfileEntity {
200+
// ✅ Correct: Helper function for creating new instances
201+
pub fn new(user_name: String, email: String, age: u32) -> Self {
202+
Self {
203+
partition_key: user_name.clone(),
204+
row_key: "profile".to_string(),
205+
time_stamp: Default::default(), // ✅ Server will set timestamp on write
206+
user_name,
207+
email,
208+
age,
209+
}
210+
}
211+
212+
// ✅ Correct: Creating with specific keys
213+
pub fn create(user_id: &str, email: String, age: u32) -> Self {
214+
Self {
215+
partition_key: user_id.to_string(),
216+
row_key: "profile".to_string(),
217+
time_stamp: Default::default(), // ✅ Always use Default::default()
218+
user_name: user_id.to_string(),
219+
email,
220+
age,
221+
}
222+
}
223+
}
224+
225+
impl Default for UserProfileEntity {
226+
fn default() -> Self {
227+
Self {
228+
partition_key: "default".to_string(),
229+
row_key: "profile".to_string(),
230+
time_stamp: Default::default(), // ✅ Correct: server will set timestamp
231+
user_name: "".to_string(),
232+
email: "".to_string(),
233+
age: 0,
234+
}
235+
}
236+
}
237+
238+
// Usage examples:
239+
// ✅ Correct: Using Default
240+
let entity1 = UserProfileEntity::default();
241+
242+
// ✅ Correct: Using helper function
243+
let entity2 = UserProfileEntity::new("john".to_string(), "john@example.com".to_string(), 30);
244+
245+
// ✅ Correct: Manual initialization
246+
let entity3 = UserProfileEntity {
247+
partition_key: "user-123".to_string(),
248+
row_key: "profile".to_string(),
249+
time_stamp: Default::default(), // ✅ Always use Default::default()
250+
user_name: "john".to_string(),
251+
email: "john@example.com".to_string(),
252+
age: 30,
253+
};
254+
255+
// ❌ WRONG: Never do this
256+
// let entity_wrong = UserProfileEntity {
257+
// partition_key: "user-123".to_string(),
258+
// row_key: "profile".to_string(),
259+
// time_stamp: Timestamp::now(), // ❌ Server will overwrite this anyway
260+
// user_name: "john".to_string(),
261+
// email: "john@example.com".to_string(),
262+
// age: 30,
263+
// };
264+
```
265+
182266
### Best practices: meaningful keys as helpers
183267
- When keys encode business meaning, provide helper functions to generate and to read them back, to avoid duplicating string literals across the codebase.
184268
- Example:
@@ -268,11 +352,13 @@ pub struct DeleteEvent {
268352
- Apply `#[serde(rename_all = "...")]` for payload fields.
269353
- Never introduce fields named `PartitionKey`, `RowKey`, `TimeStamp`, `Expires` manually unless following macro requirements.
270354
- For TTL needs, prefer `with_expires = true` over a custom `expires` unless special handling is required.
355+
- **Always initialize `time_stamp` with `Default::default()`**—never set the current timestamp manually; the server handles timestamp assignment.
271356
- Derive `Serialize`, `Deserialize`, and `Clone`; add `Debug` when useful for logs/tests.
272357
- Provide unit tests that round-trip entities and assert variant unwraps.
273358

274359
### Anti-patterns to avoid
275360
- Manually defining partition/row/timestamp fields when using the macros (causes duplication or serde conflicts).
361+
- **Setting the current timestamp manually** when creating entity instances (e.g., `time_stamp: Timestamp::now()`). The server sets timestamps automatically; use `Default::default()` instead.
276362
- Reusing the same `(partition_key, row_key)` for multiple variants in enum models.
277363
- Using dynamic keys in enum models (keys must be compile-time constants in attributes).
278364
- Introducing serde renames that clash with reserved casing tokens.

0 commit comments

Comments
 (0)