Chat Database
Location: /inc/Core/Database/Chat/Chat.php
Since: v0.2.0 (Universal Engine Architecture)
Namespace: DataMachineCoreDatabaseChat
Table: wp_datamachine_chat_sessions
Overview
ChatDatabase provides comprehensive session management for the Chat API, handling CRUD operations, user isolation, and automatic session expiration. Supports persistent conversation storage with 24-hour session lifespans.
Purpose
Centralizes all database operations for chat sessions, enabling multi-turn conversations with conversation history persistence, user-scoped access control, and automatic cleanup of expired sessions.
Database Schema
Table Structure
Table Name: wp_datamachine_chat_sessions
Columns:
CREATE TABLE wp_datamachine_chat_sessions (
session_id VARCHAR(50) NOT NULL, -- UUID4 session identifier
user_id BIGINT(20) UNSIGNED NOT NULL, -- WordPress user ID
messages LONGTEXT NOT NULL, -- JSON array of conversation messages
metadata LONGTEXT NULL, -- JSON object for session metadata
provider VARCHAR(50) NULL, -- AI provider (anthropic, openai, google, grok, openrouter)
model VARCHAR(100) NULL, -- AI model identifier (e.g., claude-3-5-sonnet-20241022)
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
expires_at DATETIME NULL, -- Auto-cleanup timestamp (24 hours from creation)
PRIMARY KEY (session_id),
KEY user_id (user_id),
KEY created_at (created_at),
KEY expires_at (expires_at)
);
Indexes:
- Primary key on
session_idfor direct session lookup - Index on
user_idfor user-scoped queries - Index on
created_atfor chronological ordering - Index on
expires_atfor efficient cleanup queries
Character Set: Uses WordPress database charset and collation
Core Methods
Table Management
create_table()
Create chat sessions table using WordPress dbDelta for safe table creation/updates.
Signature:
public static function create_table(): void
Behavior:
- Uses
dbDelta()for safe table creation (handles existing tables) - Creates indexes for efficient querying
- Logs table creation via
datamachine_logaction - Called during plugin activation
Example:
use DataMachineCoreDatabaseChatChat as ChatDatabase;
// During plugin activation
ChatDatabase::create_table();
Usage: Automatic during plugin activation, safe to call multiple times
table_exists()
Check if chat sessions table exists in database.
Signature:
public static function table_exists(): bool
Returns: True if table exists, false otherwise
Example:
if (ChatDatabase::table_exists()) {
// Table ready for use
} else {
ChatDatabase::create_table();
}
get_table_name()
Get full table name with WordPress prefix.
Signature:
public static function get_table_name(): string
Returns: Full table name (e.g., wp_datamachine_chat_sessions)
Example:
$table = ChatDatabase::get_table_name();
// Returns: "wp_datamachine_chat_sessions" (or custom prefix)
Session CRUD Operations
create_session()
Create new chat session for user.
Signature:
public function create_session(int $user_id, array $metadata = []): string
Parameters:
$user_id(int) – WordPress user ID$metadata(array) – Optional session metadata (default: empty array)
Returns: Session ID (UUID4) or empty string on failure
Default Values:
session_id: Generated UUID4messages: Empty JSON array ([])metadata: JSON-encoded metadata arrayprovider: NULLmodel: NULLexpires_at: 24 hours from creation time (GMT)
Example:
$chat_db = new ChatDatabase();
$session_id = $chat_db->create_session(
get_current_user_id(),
['created_by' => 'chat_interface', 'version' => '1.0']
);
if ($session_id) {
// Session created successfully
// Use $session_id for subsequent operations
}
Logging:
- Success: Debug log with session_id and user_id
- Failure: Error log with user_id and database error
get_session()
Retrieve session data with automatic expiration checking.
Signature:
public function get_session(string $session_id): ?array
Parameters:
$session_id(string) – Session UUID
Returns: Session data array or null if not found/expired
Returned Array Structure:
[
'session_id' => 'uuid-string',
'user_id' => 123,
'messages' => [ // Decoded from JSON
['role' => 'user', 'content' => 'Hello'],
['role' => 'assistant', 'content' => 'Hi there!']
],
'metadata' => [ // Decoded from JSON
'message_count' => 2,
'last_activity' => '2024-01-01 12:00:00'
],
'provider' => 'anthropic',
'model' => 'claude-3-5-sonnet-20241022',
'created_at' => '2024-01-01 10:00:00',
'updated_at' => '2024-01-01 12:00:00',
'expires_at' => '2024-01-02 10:00:00'
]
Expiration Handling:
- Checks
expires_attimestamp against current time - Automatically deletes expired sessions
- Returns null for expired sessions
JSON Decoding:
messagesfield decoded to PHP arraymetadatafield decoded to PHP array- Invalid JSON defaults to empty array
Example:
$chat_db = new ChatDatabase();
$session = $chat_db->get_session('uuid-abc-123');
if ($session) {
$messages = $session['messages'];
$user_id = $session['user_id'];
// Continue conversation
} else {
// Session not found or expired
// Create new session
}
Security: No user isolation check in this method – caller must verify user_id matches current user
update_session()
Update session with new messages and metadata.
Signature:
public function update_session(
string $session_id,
array $messages,
array $metadata = [],
string $provider = '',
string $model = ''
): bool
Parameters:
$session_id(string) – Session UUID$messages(array) – Complete messages array (replaces existing)$metadata(array) – Updated metadata (replaces existing)$provider(string) – AI provider (optional, only updated if non-empty)$model(string) – AI model (optional, only updated if non-empty)
Returns: True on success, false on failure
Update Behavior:
messages: Always replaced with provided array (JSON-encoded)metadata: Always replaced with provided array (JSON-encoded)provider: Only updated if non-empty string providedmodel: Only updated if non-empty string providedupdated_at: Automatically updated by database
Example:
$chat_db = new ChatDatabase();
// Get current session
$session = $chat_db->get_session('uuid-abc-123');
// Add new message to conversation
$messages = $session['messages'];
$messages[] = ['role' => 'user', 'content' => 'New message'];
// Update metadata
$metadata = $session['metadata'];
$metadata['message_count'] = count($messages);
$metadata['last_activity'] = gmdate('Y-m-d H:i:s');
// Save updates
$success = $chat_db->update_session(
'uuid-abc-123',
$messages,
$metadata,
'anthropic',
'claude-sonnet-4'
);
Logging:
- Failure: Error log with session_id and database error
Important: Caller must retrieve existing messages/metadata and merge changes – this method replaces entire arrays
delete_session()
Delete session from database.
Signature:
public function delete_session(string $session_id): bool
Parameters:
$session_id(string) – Session UUID
Returns: True on success, false on failure
Example:
$chat_db = new ChatDatabase();
$deleted = $chat_db->delete_session('uuid-abc-123');
if ($deleted) {
// Session deleted successfully
}
Logging:
- Success: Debug log with session_id
- Failure: Error log with session_id and database error
Usage:
- Manual session termination
- Automatic expiration cleanup (called by get_session)
- User logout cleanup
Maintenance
cleanup_expired_sessions()
Cleanup all expired sessions from database.
Signature:
public function cleanup_expired_sessions(): int
Returns: Number of deleted sessions
Cleanup Logic:
- Deletes sessions where
expires_at IS NOT NULL AND expires_at < NOW() - Uses GMT time for comparison
- Batch deletion for efficiency
Example:
$chat_db = new ChatDatabase();
$deleted_count = $chat_db->cleanup_expired_sessions();
// Result: 15 expired sessions deleted
Logging:
- Logs info message if any sessions deleted (includes count)
Recommended Schedule: Run via WordPress cron job (hourly or daily)
Cron Setup Example:
// Register cron event
add_action('init', function() {
if (!wp_next_scheduled('datamachine_cleanup_chat_sessions')) {
wp_schedule_event(time(), 'hourly', 'datamachine_cleanup_chat_sessions');
}
});
// Hook cleanup function
add_action('datamachine_cleanup_chat_sessions', function() {
$chat_db = new DataMachineCoreDatabaseChatChat();
$chat_db->cleanup_expired_sessions();
});
Integration with Chat API
Chat Endpoint Usage
The Chat API endpoint (/inc/Api/Chat/Chat.php) uses ChatDatabase for session management:
Session Creation:
// First message (no session_id provided)
$chat_db = new ChatDatabase();
$session_id = $chat_db->create_session(get_current_user_id());
Session Retrieval:
// Subsequent messages (session_id provided)
$session = $chat_db->get_session($session_id);
// Verify user ownership
if ($session['user_id'] !== get_current_user_id()) {
return new WP_Error('session_access_denied', 'Access denied to this session', ['status' => 403]);
}
Session Update:
// After AI response
$messages = $session['messages'];
$messages[] = ['role' => 'user', 'content' => $user_message];
$messages[] = ['role' => 'assistant', 'content' => $ai_response];
$metadata = [
'message_count' => count($messages),
'last_activity' => gmdate('Y-m-d H:i:s')
];
$chat_db->update_session($session_id, $messages, $metadata, $provider, $model);
Security Features
User Isolation
Sessions are scoped to individual WordPress users:
- Creation: Requires valid user_id
- Access: Caller must verify session user_id matches current user
- No Cross-User Access: Database queries don’t enforce this – API layer responsibility
Security Check Pattern:
$session = $chat_db->get_session($session_id);
if (!$session) {
return new WP_Error('session_not_found', 'Session not found or expired', ['status' => 404]);
}
if ($session['user_id'] !== get_current_user_id()) {
return new WP_Error('session_access_denied', 'Access denied to this session', ['status' => 403]);
}
Automatic Expiration
Sessions automatically expire after 24 hours:
- Expiration Time: Set to
NOW() + 24 hoursat creation - Cleanup: Automatic via
get_session()and manual viacleanup_expired_sessions() - Purpose: Prevent stale session accumulation
Data Storage Patterns
Messages Array
Structure:
[
['role' => 'user', 'content' => 'First user message'],
['role' => 'assistant', 'content' => 'AI response', 'tool_calls' => [...]],
['role' => 'user', 'content' => 'TOOL RESPONSE: ...'],
['role' => 'assistant', 'content' => 'Final response']
]
Storage: JSON-encoded LONGTEXT
Retrieval: JSON-decoded to PHP array
Validation: Invalid JSON defaults to empty array
Metadata Object
Common Fields:
[
'message_count' => 10,
'last_activity' => '2024-01-01 12:00:00',
'created_by' => 'chat_interface',
'version' => '1.0',
'custom_field' => 'custom_value'
]
Storage: JSON-encoded LONGTEXT
Flexibility: Arbitrary key-value pairs allowed
Retrieval: JSON-decoded to PHP array
Provider and Model Tracking
Purpose: Track which AI provider/model used for conversation
Updates: Set during first AI call, can be updated on subsequent calls
Nullable: Can be NULL if not yet set
Performance Considerations
Indexes
Optimized for common query patterns:
- session_id (PRIMARY): Direct session lookup (O(1))
- user_id: User session queries
- created_at: Chronological ordering
- expires_at: Efficient cleanup queries
JSON Storage
Benefits:
- Flexible message structure
- No schema changes needed for metadata additions
- Efficient storage for variable-length arrays
Considerations:
- JSON decoding overhead (minimal for chat usage)
- Not indexed (full messages not searchable)
- Acceptable for conversation-scoped queries
Usage Examples
Complete Session Lifecycle
use DataMachineCoreDatabaseChatChat as ChatDatabase;
$chat_db = new ChatDatabase();
$user_id = get_current_user_id();
// 1. Create new session
$session_id = $chat_db->create_session($user_id, [
'created_by' => 'rest_api',
'version' => '1.0'
]);
// 2. First message exchange
$messages = [
['role' => 'user', 'content' => 'Create a pipeline']
];
$chat_db->update_session($session_id, $messages, [
'message_count' => 1,
'last_activity' => gmdate('Y-m-d H:i:s')
]);
// 3. Continue conversation
$session = $chat_db->get_session($session_id);
$messages = $session['messages'];
$messages[] = ['role' => 'assistant', 'content' => 'I'll create a pipeline for you...'];
$chat_db->update_session($session_id, $messages, [
'message_count' => count($messages),
'last_activity' => gmdate('Y-m-d H:i:s')
], 'anthropic', 'claude-sonnet-4');
// 4. Session expires automatically after 24 hours
// Or manual cleanup:
$chat_db->cleanup_expired_sessions();
User Session Management
// Get all user sessions (custom query)
global $wpdb;
$table = ChatDatabase::get_table_name();
$user_sessions = $wpdb->get_results($wpdb->prepare(
"SELECT session_id, created_at, updated_at FROM {$table}
WHERE user_id = %d AND expires_at > %s
ORDER BY updated_at DESC",
get_current_user_id(),
current_time('mysql', true)
), ARRAY_A);
// Display active sessions to user
foreach ($user_sessions as $session_info) {
echo "Session: {$session_info['session_id']} (Updated: {$session_info['updated_at']})n";
}
Related Components
- Chat API Endpoint – REST API using ChatDatabase
- AIConversationLoop – Conversation execution
- Universal Engine Architecture – Shared AI infrastructure
- Database Schema – Complete database documentation
Location: /inc/Core/Database/Chat/Chat.php
Namespace: DataMachineCoreDatabaseChat
Table: wp_datamachine_chat_sessions
Since: v0.2.0