Files
herolib/lib/core/jobs/model/circle_manager.v
2025-03-09 22:56:33 +01:00

336 lines
8.1 KiB
V

module model
import freeflowuniverse.herolib.data.ourtime
import freeflowuniverse.herolib.data.ourdb
import freeflowuniverse.herolib.data.radixtree
import json
import os
// CircleManager handles all circle-related operations
pub struct CircleManager {
pub mut:
db_data &ourdb.OurDB // Database for storing circle data
db_meta &radixtree.RadixTree // Radix tree for mapping keys to IDs
manager Manager[Circle] // Generic manager for Circle operations
}
// new_circle_manager creates a new CircleManager instance
pub fn new_circle_manager(db_data &ourdb.OurDB, db_meta &radixtree.RadixTree) CircleManager {
return CircleManager{
db_data: db_data
db_meta: db_meta
manager: new_manager[Circle](db_data, db_meta, 'circles')
}
}
// new creates a new Circle instance
pub fn (mut m CircleManager) new() Circle {
return Circle{
id: 0
name: ''
description: ''
members: []Member{}
}
}
// set adds or updates a circle
pub fn (mut m CircleManager) set(mut circle Circle) !Circle {
// If ID is 0, use the autoincrement feature from ourdb
if circle.id == 0 {
// Store the circle with autoincrement ID
circle_data := circle.dumps()!
new_id := m.db_data.set(data: circle_data)! // ourdb now gives 1 as first id
// Update the circle ID
circle.id = new_id
// Create the key for the radix tree
key := 'circles:${new_id}'
// Store the ID in the radix tree for future lookups
m.db_meta.insert(key, new_id.str().bytes())!
// Store index keys using the generic manager
m.manager.store_index_keys(circle, new_id)!
// Update the circles:all key with this new circle
m.add_to_all_circles(new_id.str())!
} else {
// Create the key for the radix tree
key := 'circles:${circle.id}'
// Serialize the circle data using dumps
circle_data := circle.dumps()!
// Check if this circle already exists in the database
if id_bytes := m.db_meta.search(key) {
// Circle exists, get the ID and update
id_str := id_bytes.bytestr()
id := id_str.u32()
// Store the updated circle
m.db_data.set(id: id, data: circle_data)!
// Update index keys using the generic manager
m.manager.store_index_keys(circle, id)!
} else {
// Circle doesn't exist, create a new one with auto-incrementing ID
id := m.db_data.set(data: circle_data)!
// Store the ID in the radix tree for future lookups
m.db_meta.insert(key, id.str().bytes())!
// Store index keys using the generic manager
m.manager.store_index_keys(circle, id)!
// Update the circles:all key with this new circle
m.add_to_all_circles(id.str())!
}
}
return circle
}
// get retrieves a circle by its ID
pub fn (mut m CircleManager) get(id u32) !Circle {
// Create the key for the radix tree
key := 'circles:${id}'
// Get the ID from the radix tree
id_bytes := m.db_meta.search(key) or {
return error('Circle with ID ${id} not found')
}
// Convert the ID bytes to u32
id_str := id_bytes.bytestr()
db_id := id_str.u32()
// Get the circle data from the database
circle_data := m.db_data.get(db_id) or {
return error('Circle data not found for ID ${db_id}')
}
// Deserialize the circle data using circle_loads
mut circle := circle_loads(circle_data) or {
return error('Failed to deserialize circle data: ${err}')
}
return circle
}
// list returns all circles
pub fn (mut m CircleManager) list() ![]Circle {
mut circles := []Circle{}
// Get the list of all circle IDs from the special key
circle_ids := m.get_all_circle_ids() or {
// If no circles are found, return an empty list
return circles
}
// For each ID, get the circle
for id in circle_ids {
// Get the circle
circle := m.get(id) or {
// If we can't get the circle, skip it
continue
}
circles << circle
}
return circles
}
// delete removes a circle by its ID
pub fn (mut m CircleManager) delete(id u32) ! {
// Create the key for the radix tree
key := 'circles:${id}'
// Get the ID from the radix tree
id_bytes := m.db_meta.search(key) or {
return error('Circle with ID ${id} not found')
}
// Convert the ID bytes to u32
id_str := id_bytes.bytestr()
db_id := id_str.u32()
// Get the circle before deleting it to remove index keys
circle := m.get(id)!
// Delete index keys using the generic manager
m.manager.delete_index_keys(circle, id)!
// Delete the circle data from the database
m.db_data.delete(db_id)!
// Delete the key from the radix tree
m.db_meta.delete(key)!
// Remove from the circles:all list
m.remove_from_all_circles(id)!
}
// add_member adds a member to a circle
pub fn (mut m CircleManager) add_member(circle_id u32, member_pubkey string) ! {
// Get the circle
mut circle := m.get(circle_id)!
// Check if member already exists
for existing_member in circle.members {
if existing_member.pubkey == member_pubkey {
// Member already exists, nothing to do
return
}
}
// Add the new member with default role
circle.members << Member{
pubkey: member_pubkey
emails: []
name: ''
description: ''
role: .member
}
// Save the updated circle
m.set(mut circle)!
}
// remove_member removes a member from a circle
pub fn (mut m CircleManager) remove_member(circle_id u32, member_pubkey string) ! {
// Get the circle
mut circle := m.get(circle_id)!
// Filter out the member to remove
mut new_members := []Member{}
for member in circle.members {
if member.pubkey != member_pubkey {
new_members << member
}
}
// Update the circle with the new members list
circle.members = new_members
// Save the updated circle
m.set(mut circle)!
}
// find_by_index returns circles that match the given index key and value
pub fn (mut m CircleManager) find_by_index(key string, value string) ![]Circle {
// Use the generic manager to find IDs by index key
ids := m.manager.find_by_index_key(key, value)!
// Get each circle by ID
mut circles := []Circle{}
for id in ids {
circle := m.get(id) or { continue }
circles << circle
}
return circles
}
// get_user_circles returns all circles that a user is a member of
pub fn (mut m CircleManager) get_user_circles(user_pubkey string) ![]Circle {
// Get all circles
all_circles := m.list()!
mut user_circles := []Circle{}
// Check each circle for direct membership
for circle in all_circles {
for member in circle.members {
if member.pubkey == user_pubkey {
user_circles << circle
break
}
}
}
return user_circles
}
// Helper function to get all circle IDs from the special key
fn (mut m CircleManager) get_all_circle_ids() ![]u32 {
// Try to get the circles:all key
if all_bytes := m.db_meta.search('circles:all') {
// Convert to string and split by comma
all_str := all_bytes.bytestr()
if all_str.len > 0 {
str_ids := all_str.split(',')
// Convert string IDs to u32
mut u32_ids := []u32{}
for id_str in str_ids {
if id_str.len > 0 {
u32_ids << id_str.u32()
}
}
return u32_ids
}
}
return error('No circles found')
}
// Helper function to add an ID to the circles:all list
fn (mut m CircleManager) add_to_all_circles(id string) ! {
mut all_ids := []string{}
// Try to get existing list
if all_bytes := m.db_meta.search('circles:all') {
all_str := all_bytes.bytestr()
if all_str.len > 0 {
all_ids = all_str.split(',')
}
}
// Check if ID is already in the list
for existing in all_ids {
if existing == id {
// Already in the list, nothing to do
return
}
}
// Add the new ID
all_ids << id
// Join and store back
new_all := all_ids.join(',')
// Store in the radix tree
m.db_meta.insert('circles:all', new_all.bytes())!
}
// Helper function to remove an ID from the circles:all list
fn (mut m CircleManager) remove_from_all_circles(id u32) ! {
// Try to get the circles:all key
if all_bytes := m.db_meta.search('circles:all') {
// Convert to string and split by comma
all_str := all_bytes.bytestr()
if all_str.len > 0 {
all_ids := all_str.split(',')
// Filter out the ID to remove
mut new_all_ids := []string{}
for existing in all_ids {
if existing != id.str() {
new_all_ids << existing
}
}
// Join and store back
new_all := new_all_ids.join(',')
// Store in the radix tree
m.db_meta.insert('circles:all', new_all.bytes())!
}
}
}