first commit
This commit is contained in:
157
examples/README.md
Normal file
157
examples/README.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# OSIRIS Examples
|
||||
|
||||
This directory contains examples demonstrating various features of OSIRIS.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before running the examples, make sure HeroDB is running:
|
||||
|
||||
```bash
|
||||
cd /path/to/herodb
|
||||
cargo run --release -- --dir ./data --admin-secret mysecret --port 6379
|
||||
```
|
||||
|
||||
## Running Examples
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Demonstrates core OSIRIS functionality with Notes and Events:
|
||||
|
||||
```bash
|
||||
cargo run --example basic_usage
|
||||
```
|
||||
|
||||
**What it shows:**
|
||||
- Creating objects with the derive macro
|
||||
- Storing objects in HeroDB
|
||||
- Querying by indexed fields
|
||||
- Retrieving objects by ID
|
||||
- Auto-generated index keys
|
||||
- Cleanup/deletion
|
||||
|
||||
### Custom Object
|
||||
|
||||
Shows how to create your own custom object types:
|
||||
|
||||
```bash
|
||||
cargo run --example custom_object
|
||||
```
|
||||
|
||||
**What it shows:**
|
||||
- Defining custom structs with `#[derive(DeriveObject)]`
|
||||
- Using enums in indexed fields
|
||||
- Builder pattern for object construction
|
||||
- Querying by various indexed fields
|
||||
- Updating objects
|
||||
- Tag-based organization
|
||||
|
||||
## Example Structure
|
||||
|
||||
Each example follows this pattern:
|
||||
|
||||
1. **Setup** - Connect to HeroDB
|
||||
2. **Create** - Build objects using builder pattern
|
||||
3. **Store** - Save objects to HeroDB
|
||||
4. **Query** - Search by indexed fields
|
||||
5. **Retrieve** - Get objects by ID
|
||||
6. **Update** - Modify and re-store objects (where applicable)
|
||||
7. **Cleanup** - Delete test data
|
||||
|
||||
## Key Concepts Demonstrated
|
||||
|
||||
### Derive Macro
|
||||
|
||||
All examples use the `#[derive(DeriveObject)]` macro:
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, DeriveObject)]
|
||||
pub struct MyObject {
|
||||
pub base_data: BaseData,
|
||||
|
||||
#[index]
|
||||
pub indexed_field: String,
|
||||
|
||||
pub non_indexed_field: String,
|
||||
}
|
||||
```
|
||||
|
||||
### Indexed Fields
|
||||
|
||||
Fields marked with `#[index]` are automatically indexed:
|
||||
|
||||
- `Option<T>` - Indexed if Some
|
||||
- `BTreeMap<String, String>` - Each key-value pair indexed
|
||||
- `OffsetDateTime` - Indexed as date string
|
||||
- Enums - Indexed using Debug format
|
||||
- Other types - Indexed using Debug format
|
||||
|
||||
### Querying
|
||||
|
||||
Query by any indexed field:
|
||||
|
||||
```rust
|
||||
// Query by exact match
|
||||
let ids = store.get_ids_by_index("namespace", "field_name", "value").await?;
|
||||
|
||||
// Query tags (BTreeMap fields)
|
||||
let ids = store.get_ids_by_index("namespace", "tags:tag", "key=value").await?;
|
||||
```
|
||||
|
||||
### Builder Pattern
|
||||
|
||||
All objects support fluent builder pattern:
|
||||
|
||||
```rust
|
||||
let obj = MyObject::new("namespace".to_string())
|
||||
.set_field1("value1")
|
||||
.set_field2("value2")
|
||||
.add_tag("key", "value");
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Connection Refused
|
||||
|
||||
Make sure HeroDB is running on port 6379:
|
||||
|
||||
```bash
|
||||
redis-cli -p 6379 PING
|
||||
```
|
||||
|
||||
### Database Not Found
|
||||
|
||||
The examples use different database IDs:
|
||||
- `basic_usage` - DB 1
|
||||
- `custom_object` - DB 2
|
||||
|
||||
Make sure these databases are accessible in HeroDB.
|
||||
|
||||
### Compilation Errors
|
||||
|
||||
Ensure you have the latest dependencies:
|
||||
|
||||
```bash
|
||||
cargo clean
|
||||
cargo build --examples
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
After running the examples:
|
||||
|
||||
1. Read the [Architecture Documentation](../docs/ARCHITECTURE.md)
|
||||
2. Learn about the [Derive Macro](../docs/DERIVE_MACRO.md)
|
||||
3. Check out the [Quick Start Guide](../QUICKSTART.md)
|
||||
4. Explore the [source code](../src/objects/) for Note and Event implementations
|
||||
|
||||
## Creating Your Own Objects
|
||||
|
||||
Use the `custom_object` example as a template:
|
||||
|
||||
1. Define your struct with `base_data: BaseData`
|
||||
2. Add `#[derive(DeriveObject)]`
|
||||
3. Mark fields with `#[index]` for automatic indexing
|
||||
4. Implement builder methods for convenience
|
||||
5. Use `GenericStore` to store and query
|
||||
|
||||
Happy coding! 🚀
|
||||
200
examples/basic_usage.rs
Normal file
200
examples/basic_usage.rs
Normal file
@@ -0,0 +1,200 @@
|
||||
/// Basic OSIRIS usage example
|
||||
///
|
||||
/// This example demonstrates:
|
||||
/// - Creating objects with the derive macro
|
||||
/// - Storing objects in HeroDB
|
||||
/// - Querying by indexed fields
|
||||
/// - Retrieving objects
|
||||
///
|
||||
/// Prerequisites:
|
||||
/// - HeroDB running on localhost:6379
|
||||
///
|
||||
/// Run with:
|
||||
/// ```bash
|
||||
/// cargo run --example basic_usage
|
||||
/// ```
|
||||
|
||||
use osiris::objects::{Event, Note};
|
||||
use osiris::store::{BaseData, GenericStore, HeroDbClient};
|
||||
use osiris::Object;
|
||||
use std::collections::BTreeMap;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("🚀 OSIRIS Basic Usage Example\n");
|
||||
|
||||
// Initialize HeroDB client
|
||||
println!("📡 Connecting to HeroDB...");
|
||||
let client = HeroDbClient::new("redis://localhost:6379", 1)?;
|
||||
let store = GenericStore::new(client);
|
||||
println!("✓ Connected to HeroDB (DB 1)\n");
|
||||
|
||||
// ========================================
|
||||
// Part 1: Working with Notes
|
||||
// ========================================
|
||||
println!("📝 Part 1: Working with Notes");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
// Create a note with tags
|
||||
let note1 = Note::new("notes".to_string())
|
||||
.set_title("OSIRIS Architecture")
|
||||
.set_content("OSIRIS uses a trait-based architecture with automatic indexing based on #[index] attributes.")
|
||||
.add_tag("topic", "architecture")
|
||||
.add_tag("project", "osiris")
|
||||
.add_tag("priority", "high")
|
||||
.set_mime("text/plain");
|
||||
|
||||
println!("Creating note: {}", note1.title.as_ref().unwrap());
|
||||
println!(" ID: {}", note1.base_data.id);
|
||||
println!(" Tags: {:?}", note1.tags);
|
||||
|
||||
// Store the note
|
||||
store.put(¬e1).await?;
|
||||
println!("✓ Note stored\n");
|
||||
|
||||
// Create another note
|
||||
let note2 = Note::new("notes".to_string())
|
||||
.set_title("HeroDB Integration")
|
||||
.set_content("HeroDB provides encrypted storage with Redis compatibility.")
|
||||
.add_tag("topic", "storage")
|
||||
.add_tag("project", "osiris")
|
||||
.add_tag("priority", "medium")
|
||||
.set_mime("text/plain");
|
||||
|
||||
println!("Creating note: {}", note2.title.as_ref().unwrap());
|
||||
println!(" ID: {}", note2.base_data.id);
|
||||
store.put(¬e2).await?;
|
||||
println!("✓ Note stored\n");
|
||||
|
||||
// Retrieve a note by ID
|
||||
println!("Retrieving note by ID...");
|
||||
let retrieved_note: Note = store.get("notes", ¬e1.base_data.id).await?;
|
||||
println!("✓ Retrieved: {}", retrieved_note.title.as_ref().unwrap());
|
||||
println!(" Content: {}\n", retrieved_note.content.as_ref().unwrap_or(&"(none)".to_string()));
|
||||
|
||||
// Query notes by tag
|
||||
println!("Querying notes by tag (project=osiris)...");
|
||||
let ids = store.get_ids_by_index("notes", "tags:tag", "project=osiris").await?;
|
||||
println!("✓ Found {} notes with tag project=osiris", ids.len());
|
||||
for id in &ids {
|
||||
let note: Note = store.get("notes", id).await?;
|
||||
println!(" - {}", note.title.as_ref().unwrap_or(&"(untitled)".to_string()));
|
||||
}
|
||||
println!();
|
||||
|
||||
// Query by different tag
|
||||
println!("Querying notes by tag (priority=high)...");
|
||||
let high_priority_ids = store.get_ids_by_index("notes", "tags:tag", "priority=high").await?;
|
||||
println!("✓ Found {} high-priority notes\n", high_priority_ids.len());
|
||||
|
||||
// ========================================
|
||||
// Part 2: Working with Events
|
||||
// ========================================
|
||||
println!("📅 Part 2: Working with Events");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
use osiris::objects::event::EventStatus;
|
||||
|
||||
// Create an event
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let event1 = Event::new("calendar".to_string(), "Team Standup")
|
||||
.set_description("Daily standup meeting")
|
||||
.set_start_time(now)
|
||||
.set_end_time(now + time::Duration::minutes(30))
|
||||
.set_location("Room 101")
|
||||
.set_status(EventStatus::Published)
|
||||
.set_category("meetings")
|
||||
.set_all_day(false);
|
||||
|
||||
println!("Creating event: {}", event1.title);
|
||||
println!(" ID: {}", event1.base_data.id);
|
||||
println!(" Location: {}", event1.location.as_ref().unwrap());
|
||||
println!(" Status: {:?}", event1.status);
|
||||
|
||||
store.put(&event1).await?;
|
||||
println!("✓ Event stored\n");
|
||||
|
||||
// Create another event
|
||||
let tomorrow = now + time::Duration::days(1);
|
||||
let event2 = Event::new("calendar".to_string(), "Project Review")
|
||||
.set_description("Review OSIRIS implementation progress")
|
||||
.set_start_time(tomorrow)
|
||||
.set_end_time(tomorrow + time::Duration::hours(1))
|
||||
.set_location("Conference Room A")
|
||||
.set_status(EventStatus::Published)
|
||||
.set_category("reviews");
|
||||
|
||||
println!("Creating event: {}", event2.title);
|
||||
store.put(&event2).await?;
|
||||
println!("✓ Event stored\n");
|
||||
|
||||
// Query events by location
|
||||
println!("Querying events by location (Room 101)...");
|
||||
let location_ids = store.get_ids_by_index("calendar", "location", "Room 101").await?;
|
||||
println!("✓ Found {} events in Room 101", location_ids.len());
|
||||
for id in &location_ids {
|
||||
let event: Event = store.get("calendar", id).await?;
|
||||
println!(" - {}", event.title);
|
||||
}
|
||||
println!();
|
||||
|
||||
// Query events by status
|
||||
println!("Querying events by status (Published)...");
|
||||
let status_ids = store.get_ids_by_index("calendar", "status", "Published").await?;
|
||||
println!("✓ Found {} published events", status_ids.len());
|
||||
for id in &status_ids {
|
||||
let event: Event = store.get("calendar", id).await?;
|
||||
println!(" - {} ({})", event.title, event.category.as_ref().unwrap_or(&"uncategorized".to_string()));
|
||||
}
|
||||
println!();
|
||||
|
||||
// Query events by date
|
||||
let date_str = now.date().to_string();
|
||||
println!("Querying events by date ({})...", date_str);
|
||||
let date_ids = store.get_ids_by_index("calendar", "start_time", &date_str).await?;
|
||||
println!("✓ Found {} events on {}", date_ids.len(), date_str);
|
||||
println!();
|
||||
|
||||
// ========================================
|
||||
// Part 3: Demonstrating Auto-Generated Indexes
|
||||
// ========================================
|
||||
println!("🔍 Part 3: Auto-Generated Indexes");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
println!("Note indexed fields: {:?}", Note::indexed_fields());
|
||||
println!("Event indexed fields: {:?}", Event::indexed_fields());
|
||||
println!();
|
||||
|
||||
println!("Note index keys for '{}': ", note1.title.as_ref().unwrap());
|
||||
for key in note1.index_keys() {
|
||||
println!(" - {} = {}", key.name, key.value);
|
||||
}
|
||||
println!();
|
||||
|
||||
println!("Event index keys for '{}': ", event1.title);
|
||||
for key in event1.index_keys() {
|
||||
println!(" - {} = {}", key.name, key.value);
|
||||
}
|
||||
println!();
|
||||
|
||||
// ========================================
|
||||
// Part 4: Cleanup
|
||||
// ========================================
|
||||
println!("🧹 Part 4: Cleanup");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
println!("Deleting notes...");
|
||||
store.delete(¬e1).await?;
|
||||
store.delete(¬e2).await?;
|
||||
println!("✓ Notes deleted\n");
|
||||
|
||||
println!("Deleting events...");
|
||||
store.delete(&event1).await?;
|
||||
store.delete(&event2).await?;
|
||||
println!("✓ Events deleted\n");
|
||||
|
||||
println!("✅ Example completed successfully!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
295
examples/custom_object.rs
Normal file
295
examples/custom_object.rs
Normal file
@@ -0,0 +1,295 @@
|
||||
/// Custom Object Example
|
||||
///
|
||||
/// This example demonstrates how to create your own custom object types
|
||||
/// using the derive macro.
|
||||
///
|
||||
/// Run with:
|
||||
/// ```bash
|
||||
/// cargo run --example custom_object
|
||||
/// ```
|
||||
|
||||
use osiris::store::{BaseData, GenericStore, HeroDbClient};
|
||||
use osiris::{DeriveObject, Object};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::BTreeMap;
|
||||
use time::OffsetDateTime;
|
||||
|
||||
// ========================================
|
||||
// Custom Object: Task
|
||||
// ========================================
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub enum TaskPriority {
|
||||
Low,
|
||||
Medium,
|
||||
High,
|
||||
Critical,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub enum TaskStatus {
|
||||
Todo,
|
||||
InProgress,
|
||||
Done,
|
||||
Blocked,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, DeriveObject)]
|
||||
pub struct Task {
|
||||
pub base_data: BaseData,
|
||||
|
||||
/// Task title
|
||||
#[index]
|
||||
pub title: String,
|
||||
|
||||
/// Task description
|
||||
pub description: Option<String>,
|
||||
|
||||
/// Priority level
|
||||
#[index]
|
||||
pub priority: TaskPriority,
|
||||
|
||||
/// Current status
|
||||
#[index]
|
||||
pub status: TaskStatus,
|
||||
|
||||
/// Assigned to user
|
||||
#[index]
|
||||
pub assignee: Option<String>,
|
||||
|
||||
/// Due date
|
||||
#[index]
|
||||
#[serde(with = "time::serde::rfc3339::option")]
|
||||
pub due_date: Option<OffsetDateTime>,
|
||||
|
||||
/// Tags for categorization
|
||||
#[index]
|
||||
pub tags: BTreeMap<String, String>,
|
||||
|
||||
/// Estimated hours
|
||||
pub estimated_hours: Option<f32>,
|
||||
|
||||
/// Actual hours spent
|
||||
pub actual_hours: Option<f32>,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
pub fn new(ns: String, title: impl ToString) -> Self {
|
||||
Self {
|
||||
base_data: BaseData::new(ns),
|
||||
title: title.to_string(),
|
||||
description: None,
|
||||
priority: TaskPriority::Medium,
|
||||
status: TaskStatus::Todo,
|
||||
assignee: None,
|
||||
due_date: None,
|
||||
tags: BTreeMap::new(),
|
||||
estimated_hours: None,
|
||||
actual_hours: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_description(mut self, description: impl ToString) -> Self {
|
||||
self.description = Some(description.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_priority(mut self, priority: TaskPriority) -> Self {
|
||||
self.priority = priority;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_status(mut self, status: TaskStatus) -> Self {
|
||||
self.status = status;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_assignee(mut self, assignee: impl ToString) -> Self {
|
||||
self.assignee = Some(assignee.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_due_date(mut self, due_date: OffsetDateTime) -> Self {
|
||||
self.due_date = Some(due_date);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_tag(mut self, key: impl ToString, value: impl ToString) -> Self {
|
||||
self.tags.insert(key.to_string(), value.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_estimated_hours(mut self, hours: f32) -> Self {
|
||||
self.estimated_hours = Some(hours);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Main Example
|
||||
// ========================================
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("🎯 OSIRIS Custom Object Example\n");
|
||||
|
||||
// Connect to HeroDB
|
||||
println!("📡 Connecting to HeroDB...");
|
||||
let client = HeroDbClient::new("redis://localhost:6379", 2)?;
|
||||
let store = GenericStore::new(client);
|
||||
println!("✓ Connected to HeroDB (DB 2)\n");
|
||||
|
||||
// ========================================
|
||||
// Create Tasks
|
||||
// ========================================
|
||||
println!("📋 Creating Tasks");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
let now = OffsetDateTime::now_utc();
|
||||
let tomorrow = now + time::Duration::days(1);
|
||||
let next_week = now + time::Duration::days(7);
|
||||
|
||||
// Task 1: High priority, assigned
|
||||
let task1 = Task::new("tasks".to_string(), "Implement derive macro")
|
||||
.set_description("Create proc macro for automatic Object trait implementation")
|
||||
.set_priority(TaskPriority::High)
|
||||
.set_status(TaskStatus::Done)
|
||||
.set_assignee("alice")
|
||||
.set_due_date(tomorrow)
|
||||
.add_tag("component", "derive")
|
||||
.add_tag("project", "osiris")
|
||||
.set_estimated_hours(8.0);
|
||||
|
||||
println!("Task 1: {}", task1.title);
|
||||
println!(" Priority: {:?}", task1.priority);
|
||||
println!(" Status: {:?}", task1.status);
|
||||
println!(" Assignee: {}", task1.assignee.as_ref().unwrap());
|
||||
store.put(&task1).await?;
|
||||
println!("✓ Stored\n");
|
||||
|
||||
// Task 2: Critical priority, blocked
|
||||
let task2 = Task::new("tasks".to_string(), "Fix indexing bug")
|
||||
.set_description("BTreeMap indexing has lifetime issues")
|
||||
.set_priority(TaskPriority::Critical)
|
||||
.set_status(TaskStatus::Blocked)
|
||||
.set_assignee("bob")
|
||||
.set_due_date(now)
|
||||
.add_tag("type", "bug")
|
||||
.add_tag("project", "osiris")
|
||||
.set_estimated_hours(4.0);
|
||||
|
||||
println!("Task 2: {}", task2.title);
|
||||
println!(" Priority: {:?}", task2.priority);
|
||||
println!(" Status: {:?}", task2.status);
|
||||
store.put(&task2).await?;
|
||||
println!("✓ Stored\n");
|
||||
|
||||
// Task 3: In progress
|
||||
let task3 = Task::new("tasks".to_string(), "Write documentation")
|
||||
.set_description("Document the derive macro usage")
|
||||
.set_priority(TaskPriority::Medium)
|
||||
.set_status(TaskStatus::InProgress)
|
||||
.set_assignee("alice")
|
||||
.set_due_date(next_week)
|
||||
.add_tag("type", "docs")
|
||||
.add_tag("project", "osiris")
|
||||
.set_estimated_hours(6.0);
|
||||
|
||||
println!("Task 3: {}", task3.title);
|
||||
println!(" Priority: {:?}", task3.priority);
|
||||
println!(" Status: {:?}", task3.status);
|
||||
store.put(&task3).await?;
|
||||
println!("✓ Stored\n");
|
||||
|
||||
// ========================================
|
||||
// Query Tasks
|
||||
// ========================================
|
||||
println!("🔍 Querying Tasks");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
// Query by assignee
|
||||
println!("Tasks assigned to Alice:");
|
||||
let alice_tasks = store.get_ids_by_index("tasks", "assignee", "alice").await?;
|
||||
for id in &alice_tasks {
|
||||
let task: Task = store.get("tasks", id).await?;
|
||||
println!(" - {} ({:?})", task.title, task.status);
|
||||
}
|
||||
println!();
|
||||
|
||||
// Query by priority
|
||||
println!("High priority tasks:");
|
||||
let high_priority = store.get_ids_by_index("tasks", "priority", "High").await?;
|
||||
for id in &high_priority {
|
||||
let task: Task = store.get("tasks", id).await?;
|
||||
println!(" - {} (assigned to: {})",
|
||||
task.title,
|
||||
task.assignee.as_ref().unwrap_or(&"unassigned".to_string())
|
||||
);
|
||||
}
|
||||
println!();
|
||||
|
||||
// Query by status
|
||||
println!("Blocked tasks:");
|
||||
let blocked = store.get_ids_by_index("tasks", "status", "Blocked").await?;
|
||||
for id in &blocked {
|
||||
let task: Task = store.get("tasks", id).await?;
|
||||
println!(" - {} (priority: {:?})", task.title, task.priority);
|
||||
}
|
||||
println!();
|
||||
|
||||
// Query by tag
|
||||
println!("Tasks tagged with project=osiris:");
|
||||
let project_tasks = store.get_ids_by_index("tasks", "tags:tag", "project=osiris").await?;
|
||||
println!(" Found {} tasks", project_tasks.len());
|
||||
println!();
|
||||
|
||||
// ========================================
|
||||
// Show Auto-Generated Indexes
|
||||
// ========================================
|
||||
println!("📊 Auto-Generated Indexes");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
println!("Task indexed fields: {:?}", Task::indexed_fields());
|
||||
println!();
|
||||
|
||||
println!("Index keys for '{}':", task1.title);
|
||||
for key in task1.index_keys() {
|
||||
println!(" - {} = {}", key.name, key.value);
|
||||
}
|
||||
println!();
|
||||
|
||||
// ========================================
|
||||
// Update Task Status
|
||||
// ========================================
|
||||
println!("✏️ Updating Task Status");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
// Retrieve, modify, and store
|
||||
let mut task2_updated: Task = store.get("tasks", &task2.base_data.id).await?;
|
||||
println!("Updating '{}' status from {:?} to {:?}",
|
||||
task2_updated.title,
|
||||
task2_updated.status,
|
||||
TaskStatus::InProgress
|
||||
);
|
||||
|
||||
task2_updated.status = TaskStatus::InProgress;
|
||||
task2_updated.base_data.update_modified();
|
||||
|
||||
store.put(&task2_updated).await?;
|
||||
println!("✓ Task updated\n");
|
||||
|
||||
// ========================================
|
||||
// Cleanup
|
||||
// ========================================
|
||||
println!("🧹 Cleanup");
|
||||
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
|
||||
|
||||
store.delete(&task1).await?;
|
||||
store.delete(&task2_updated).await?;
|
||||
store.delete(&task3).await?;
|
||||
println!("✓ All tasks deleted\n");
|
||||
|
||||
println!("✅ Example completed successfully!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user