Familia v2.0 Documentation
Welcome to the comprehensive documentation for Familia v2.0. This guide collection provides detailed explanations of all major features including security, connection management, architecture, and object relationships.
📖 Documentation Layers
- Overview - Conceptual introduction and getting started
- Technical Reference - Implementation patterns and technical details
- This Guide Collection - Deep-dive topic guides with detailed prose and examples
📚 Guide Structure
🏗️ Architecture & System Design
- Feature System - Modular architecture with dependencies and autoloader patterns
- Feature System for Developers - Advanced feature development patterns
- Field System - Field definitions and data type mappings
- Logging - Logger configuration and database command logging
🔐 Security & Special Fields
- Encrypted Fields - Persistent encrypted storage with modular providers
- Transient Fields - Non-persistent secure data handling with RedactedString
- Encryption Guide - Legacy encryption documentation
- Object Identifiers - Automatic ID generation with configurable strategies
- External Identifiers - Integration with external systems and legacy data
🔗 Object Relationships
- Relationships - Object relationships and membership system
- Relationship Methods - Detailed method reference for relationships
⏱️ Time & Analytics Features
- Expiration - TTL management and cascading expiration
- Quantization - Time-based data bucketing for analytics
- Time Literals - Time manipulation and formatting utilities
🛠️ Implementation & Usage
- Optimized Loading - Reduce Redis commands by 50-96% for bulk object loading (new!)
🚀 Quick Start Examples
Encrypted Fields (Persistent)
class User < Familia::Horreum
feature :encrypted_fields
encrypted_field :secret_recipe
end
# Configure encryption
Familia.configure do |config|
config.encryption_keys = { v1: ENV['FAMILIA_ENCRYPTION_KEY'] }
config.current_key_version = :v1
end
user = User.new(secret_recipe: "donna's cookies")
user.save
user.secret_recipe # => "donna's cookies" (automatically decrypted)
Feature System (Modular)
class Customer < Familia::Horreum
feature :safe_dump # API-safe serialization
feature :expiration # TTL support
feature :encrypted_fields # Secure storage
field :name, :email
encrypted_field :api_key
default_expiration 24.hours
safe_dump_fields :name, :email
end
Connection Pooling (Performance)
# Configure connection provider for multi-database pooling
Familia.connection_provider = lambda do |uri|
parsed = URI.parse(uri) # => URI::Redis
pool_key = "#{parsed.host}:#{parsed.port}/#{parsed.db || 0}"
@pools[pool_key] ||= ConnectionPool.new(size: 10) do
Redis.new(host: parsed.host, port: parsed.port, db: parsed.db || 0)
end
@pools[pool_key].with { |conn| conn }
end
Object Relationships
class Customer < Familia::Horreum
feature :relationships
identifier_field :custid
field :custid, :name, :email
set :domains # Customer collections
end
class Domain < Familia::Horreum
feature :relationships
identifier_field :domain_id
field :domain_id, :name, :dns_zone
participates_in Customer, :domains # Bidirectional membership
end
# Create objects and establish relationships
customer = Customer.new(custid: "cust123", name: "Acme Corp")
domain = Domain.new(domain_id: "dom456", name: "acme.com")
# Ruby-like syntax for relationships
customer.domains << domain # Clean collection syntax
# Query relationships
domain.in_customer_domains?(customer.custid) # => true
customer.domains.member?(domain.identifier) # => true
Object Identifiers (Auto-generation)
class Document < Familia::Horreum
feature :object_identifier, generator: :uuid_v4
field :title, :content
end
class Session < Familia::Horreum
feature :object_identifier, generator: :hex
field :user_id, :data
end
# Automatic ID generation
doc = Document.create(title: "My Document")
doc.objid # => "f47ac10b-58cc-4372-a567-0e02b2c3d479"
session = Session.create(user_id: "123")
session.objid # => "a1b2c3d4e5f6"
External Identifiers (Legacy Integration)
class ExternalUser < Familia::Horreum
feature :external_identifier
field :internal_id, :external_id, :name
end
# Map external system IDs to internal objects
user = ExternalUser.create(
internal_id: SecureRandom.uuid,
external_id: "ext_12345",
name: "Legacy User"
)
# Find by external ID
found = ExternalUser.find_by_external_id("ext_12345")
Quantization (Analytics)
class MetricsBucket < Familia::Horreum
feature :quantization
field :metric_key, :value_count
string :counter, quantize: [10.minutes, '%H:%M']
end
# Automatic time bucketing for analytics
MetricsBucket.record_event("page_view") # Groups into 10-min buckets
Optimized Loading (Performance)
# Skip EXISTS check (50% reduction)
user = User.find_by_id(123, check_exists: false)
# Pipelined bulk loading (96% reduction for N objects)
= customer..rangebyscore(start_time, end_time)
# => ["id1", "id2", ..., "id14"] # 14 metadata objects
# Traditional: 28 Redis commands (14 EXISTS + 14 HGETALL)
= .map { |id| Metadata.find_by_id(id) }
# Optimized: 1 pipelined batch with 14 HGETALL commands
= Metadata.load_multi().compact
Related Resources
- Familia README - Main project documentation
- Issue #57 - Original feature proposal
- Issue #58 - Wiki documentation tracking