refactor: reorganise optional SQL scripts by database type

The optional SQL directory contained a single PostgreSQL script with no
clear organisation. As we now have scripts for both PostgreSQL and MSSQL,
and multiple test scenarios (message generation, room creation, performance
testing), a clearer structure is needed.

Reorganises into postgresql/ and mssql/ subdirectories with descriptive
filenames that indicate purpose rather than execution order. Adds README
documenting available scripts and usage patterns.

Key scripts preserved:
- 410k message generator (PostgreSQL + MSSQL)
- 50 room creator with message redistribution (PostgreSQL + MSSQL)
- 10,000 minimal rooms for scale testing (PostgreSQL)
- 200 rooms with realistic affiliations and messages (PostgreSQL)
- Worker count configuration template (PostgreSQL)
feat/add-optional-sql-scripts
Matthew Vivian 2025-12-12 12:27:06 +00:00
parent f96acacafb
commit 582c7269c9
No known key found for this signature in database
GPG Key ID: BADAD4A1EE1C9B34
8 changed files with 775 additions and 11 deletions

View File

@ -0,0 +1,82 @@
# Optional SQL Scripts
This directory contains optional SQL scripts for generating test data in Openfire Docker environments. These scripts are useful for performance testing, debugging, and simulating production-like environments.
## Directory Structure
```
optional/sql/
├── postgresql/ # Scripts for PostgreSQL databases
│ ├── generate-test-messages.sql
│ ├── create-50-rooms.sql
│ ├── performance-test-10000-rooms.sql
│ ├── performance-test-200-rooms-with-data.sql
│ └── set-worker-count.sql
└── mssql/ # Scripts for Microsoft SQL Server
├── generate-test-messages.sql
└── create-50-rooms.sql
```
## Available Scripts
### PostgreSQL Scripts
| Script | Purpose |
|--------|---------|
| `generate-test-messages.sql` | Generates ~410,000 MUC messages across 2 rooms. Useful for testing slow startup issues due to large message history. |
| `create-50-rooms.sql` | Creates 48 additional rooms (IDs 3-50) and redistributes messages across all 50 rooms. |
| `performance-test-10000-rooms.sql` | Creates 10,000 minimal rooms with single owner affiliation. Ideal for testing room loading at scale without message history overhead. |
| `performance-test-200-rooms-with-data.sql` | Creates 200 rooms with realistic data: varied affiliations (owners, admins, members) and 100-500 messages per room (~60,000 total). |
| `set-worker-count.sql` | Template for setting the `xmpp.muc.loading.workers` property to control parallel room loading. |
### MSSQL Scripts
| Script | Purpose |
|--------|---------|
| `generate-test-messages.sql` | MSSQL version of the 410,000 message generator. |
| `create-50-rooms.sql` | MSSQL version of the 50 rooms creator. |
## Usage
### Option 1: Copy to deployment directory (recommended for testing)
Copy the desired script to your deployment's `sql/` directory with a numbered prefix:
```bash
# For simple deployment with 10,000 rooms
cp optional/sql/postgresql/performance-test-10000-rooms.sql simple/sql/001-perf-rooms.sql
# Start fresh (removes existing database)
./start.sh
```
Scripts in the `sql/` directory run automatically on container startup via PostgreSQL's `docker-entrypoint-initdb.d` mechanism.
### Option 2: Run manually against running database
```bash
# PostgreSQL example
docker exec -i simple-db-1 psql -U openfire -d openfire \
< optional/sql/postgresql/generate-test-messages.sql
# MSSQL example
docker exec -it mssql_server /opt/mssql-tools18/bin/sqlcmd \
-S localhost -U sa -P 'YourPassword' -d openfire -C \
-i /path/to/script.sql
```
## Choosing a Test Dataset
| Use Case | Recommended Script |
|----------|-------------------|
| Test MUC history loading performance | `generate-test-messages.sql` + `create-50-rooms.sql` |
| Test room loading at scale (many rooms, no messages) | `performance-test-10000-rooms.sql` |
| Test realistic room loading (rooms with affiliations + messages) | `performance-test-200-rooms-with-data.sql` |
| Test parallel worker configuration | Any data script + `set-worker-count.sql` |
## Notes
- Scripts numbered `001-*` onwards run after `000-init-openfire.sql` (the base schema)
- Some scripts (like `create-50-rooms.sql`) expect existing rooms/messages to work with
- Performance test scripts replace existing rooms, so use on fresh databases
- Worker count changes require an Openfire restart to take effect

View File

@ -0,0 +1,122 @@
-- =============================================================================
-- Create 50 MUC Rooms - MSSQL
-- =============================================================================
--
-- Database: Microsoft SQL Server
-- Compatibility: MSSQL deployments (cluster_mssql)
--
-- Purpose:
-- Creates 48 additional MUC rooms (IDs 3-50) to supplement the 2 default rooms,
-- giving a total of ~50 rooms. Also redistributes any existing messages evenly
-- across all 50 rooms.
--
-- Useful for testing environments that need a moderate number of rooms with
-- message history spread across them.
--
-- Prerequisites:
-- - Rooms with IDs 1 and 2 should already exist
-- - Best used after generate-test-messages.sql to have messages to redistribute
--
-- Usage:
-- Run manually against a running MSSQL database:
--
-- docker exec -it mssql_server /opt/mssql-tools18/bin/sqlcmd \
-- -S localhost -U sa -P 'YourPassword' -d openfire -C \
-- -i /path/to/create-50-rooms.sql
--
-- =============================================================================
USE openfire;
GO
SET NOCOUNT ON;
GO
DECLARE @i INT = 3;
DECLARE @room_name VARCHAR(50);
DECLARE @creation_time CHAR(15);
DECLARE @base_time BIGINT = CAST(DATEDIFF(SECOND, '1970-01-01', GETDATE()) AS BIGINT) * 1000;
PRINT 'Creating additional MUC rooms...';
PRINT 'Current time (ms): ' + CAST(@base_time AS VARCHAR(20));
-- Create rooms 3 through 50 (48 additional rooms)
WHILE @i <= 50
BEGIN
SET @room_name = 'muc' + CAST(@i AS VARCHAR(10));
SET @creation_time = RIGHT(REPLICATE('0', 15) + CAST(@base_time - (@i * 1000) AS VARCHAR(15)), 15);
INSERT INTO ofMucRoom (
serviceID, roomID, creationDate, modificationDate, name, naturalName, description,
lockedDate, emptyDate, canChangeSubject, maxUsers, publicRoom, moderated,
membersOnly, canInvite, roomPassword, canDiscoverJID, logEnabled,
retireOnDeletion, preserveHistOnDel, subject, rolesToBroadcast,
useReservedNick, canChangeNick, canRegister, allowpm, fmucEnabled,
fmucOutboundNode, fmucOutboundMode, fmucInboundNodes
)
VALUES (
1, -- serviceID
@i, -- roomID
@creation_time, -- creationDate
@creation_time, -- modificationDate
@room_name, -- name
@room_name, -- naturalName
@room_name, -- description
'000000000000000', -- lockedDate (not locked)
@creation_time, -- emptyDate
0, -- canChangeSubject
30, -- maxUsers
1, -- publicRoom
0, -- moderated
0, -- membersOnly
0, -- canInvite
NULL, -- roomPassword
1, -- canDiscoverJID
1, -- logEnabled
0, -- retireOnDeletion
1, -- preserveHistOnDel
'', -- subject
7, -- rolesToBroadcast
0, -- useReservedNick
1, -- canChangeNick
1, -- canRegister
0, -- allowpm
0, -- fmucEnabled
NULL, -- fmucOutboundNode
NULL, -- fmucOutboundMode
NULL -- fmucInboundNodes
);
IF @i % 10 = 0
BEGIN
PRINT 'Created room: ' + @room_name;
END
SET @i = @i + 1;
END
PRINT 'Room creation complete.';
GO
-- Now redistribute messages across all 50 rooms
-- This simulates a more realistic distribution where each room has messages
PRINT 'Redistributing messages across all 50 rooms...';
UPDATE ofMucConversationLog
SET roomID = (messageID % 50) + 1;
PRINT 'Message redistribution complete.';
GO
-- Verify
PRINT '';
PRINT '=== Verification ===';
SELECT 'Total rooms: ' + CAST(COUNT(*) AS VARCHAR(10)) AS result FROM ofMucRoom;
SELECT 'Total messages: ' + CAST(COUNT(*) AS VARCHAR(10)) AS result FROM ofMucConversationLog;
SELECT 'Messages per room (sample):' AS result;
SELECT TOP 10
'Room ' + CAST(roomID AS VARCHAR(5)) + ': ' + CAST(COUNT(*) AS VARCHAR(10)) + ' messages' AS result
FROM ofMucConversationLog
GROUP BY roomID
ORDER BY roomID;
GO

View File

@ -0,0 +1,105 @@
-- =============================================================================
-- Generate Test Messages (~410,000) - MSSQL
-- =============================================================================
--
-- Database: Microsoft SQL Server
-- Compatibility: MSSQL deployments (cluster_mssql)
--
-- Purpose:
-- Generates ~410,000 MUC messages distributed across 2 rooms to simulate a
-- long-running environment experiencing slow startup due to large message
-- history. Useful for testing MUC history loading performance.
--
-- Prerequisites:
-- - Rooms with IDs 1 and 2 must exist (messages alternate between them)
-- - Database should be initialised with Openfire schema
--
-- Usage:
-- Run manually against a running MSSQL database:
--
-- docker exec -it mssql_server /opt/mssql-tools18/bin/sqlcmd \
-- -S localhost -U sa -P 'YourPassword' -d openfire -C \
-- -i /path/to/generate-test-messages.sql
--
-- =============================================================================
USE openfire;
GO
SET NOCOUNT ON;
GO
DECLARE @base_time BIGINT = CAST(DATEDIFF(SECOND, '1970-01-01', GETDATE()) AS BIGINT) * 1000;
DECLARE @msg_id INT = 100;
DECLARE @i INT = 1;
DECLARE @room_id INT;
DECLARE @log_time CHAR(15);
DECLARE @batch_size INT = 1000;
PRINT 'Starting message generation at ' + CONVERT(VARCHAR, GETDATE(), 120);
PRINT 'Base time: ' + CAST(@base_time AS VARCHAR(20));
-- Use batch inserts for better performance
WHILE @i <= 410000
BEGIN
BEGIN TRANSACTION;
DECLARE @batch_end INT = @i + @batch_size - 1;
IF @batch_end > 410000 SET @batch_end = 410000;
WHILE @i <= @batch_end
BEGIN
SET @room_id = (@i % 2) + 1;
SET @log_time = RIGHT(REPLICATE('0', 15) + CAST(@base_time - (CAST(@i AS BIGINT) * 6480) AS VARCHAR(15)), 15);
INSERT INTO ofMucConversationLog (roomID, messageID, sender, nickname, logTime, subject, body, stanza)
VALUES (
@room_id,
@msg_id,
'user1@xmpp.localhost.example/resource',
'User One',
@log_time,
NULL,
'Test message ' + CAST(@i AS VARCHAR(10)),
NULL
);
SET @msg_id = @msg_id + 1;
SET @i = @i + 1;
END
COMMIT TRANSACTION;
IF (@i - 1) % 50000 = 0
BEGIN
PRINT 'Progress: ' + CAST(@i - 1 AS VARCHAR(10)) + ' messages inserted';
END
END
PRINT 'Message generation complete at ' + CONVERT(VARCHAR, GETDATE(), 120);
GO
-- Set long history configuration using MERGE (MSSQL equivalent of ON CONFLICT)
MERGE INTO ofMucServiceProp AS target
USING (SELECT 1 AS serviceID, 'history.maxNumber' AS name, '1000' AS propValue) AS source
ON target.serviceID = source.serviceID AND target.name = source.name
WHEN MATCHED THEN UPDATE SET propValue = source.propValue
WHEN NOT MATCHED THEN INSERT (serviceID, name, propValue) VALUES (source.serviceID, source.name, source.propValue);
GO
MERGE INTO ofMucServiceProp AS target
USING (SELECT 1 AS serviceID, 'history.type' AS name, 'number' AS propValue) AS source
ON target.serviceID = source.serviceID AND target.name = source.name
WHEN MATCHED THEN UPDATE SET propValue = source.propValue
WHEN NOT MATCHED THEN INSERT (serviceID, name, propValue) VALUES (source.serviceID, source.name, source.propValue);
GO
-- Ensure NO reload limit (worst case scenario)
DELETE FROM ofProperty WHERE name = 'xmpp.muc.history.reload.limit';
GO
-- Verify
SELECT 'Total messages: ' + CAST(COUNT(*) AS VARCHAR(10)) AS result FROM ofMucConversationLog;
SELECT 'Room ' + CAST(roomID AS VARCHAR(5)) + ': ' + CAST(COUNT(*) AS VARCHAR(10)) + ' messages' AS result
FROM ofMucConversationLog GROUP BY roomID ORDER BY roomID;
GO

View File

@ -0,0 +1,115 @@
-- =============================================================================
-- Create 50 MUC Rooms - PostgreSQL
-- =============================================================================
--
-- Database: PostgreSQL
-- Compatibility: All PostgreSQL deployments (simple, cluster, federation, etc.)
--
-- Purpose:
-- Creates 48 additional MUC rooms (IDs 3-50) to supplement the 2 default rooms,
-- giving a total of ~50 rooms. Also redistributes any existing messages evenly
-- across all 50 rooms.
--
-- Useful for testing environments that need a moderate number of rooms with
-- message history spread across them.
--
-- Prerequisites:
-- - Rooms with IDs 1 and 2 should already exist (from 000-init-openfire.sql)
-- - Best used after generate-test-messages.sql to have messages to redistribute
--
-- Usage:
-- Option 1 - Copy to deployment's sql/ directory (runs on container start):
--
-- cp optional/sql/postgresql/create-50-rooms.sql simple/sql/002-create-50-rooms.sql
-- ./start.sh
--
-- Option 2 - Run manually against a running database:
--
-- docker exec -i simple-db-1 psql -U openfire -d openfire \
-- < optional/sql/postgresql/create-50-rooms.sql
--
-- =============================================================================
DO $$
DECLARE
i INTEGER;
room_name VARCHAR(50);
creation_time CHAR(15);
base_time BIGINT := (EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT;
BEGIN
RAISE NOTICE 'Creating additional MUC rooms...';
RAISE NOTICE 'Current time (ms): %', base_time;
-- Create rooms 3 through 50 (48 additional rooms)
FOR i IN 3..50 LOOP
room_name := 'muc' || i::TEXT;
creation_time := LPAD((base_time - (i * 1000))::TEXT, 15, '0');
INSERT INTO ofmucroom (
serviceid, roomid, creationdate, modificationdate, name, naturalname, description,
lockeddate, emptydate, canchangesubject, maxusers, publicroom, moderated,
membersonly, caninvite, roompassword, candiscoverjid, logenabled,
subject, rolestobroadcast,
usereservednick, canchangenick, canregister, allowpm, fmucenabled,
fmucoutboundnode, fmucoutboundmode, fmucinboundnodes
)
VALUES (
1, -- serviceid
i, -- roomid
creation_time, -- creationdate
creation_time, -- modificationdate
room_name, -- name
room_name, -- naturalname
room_name, -- description
'000000000000000', -- lockeddate (not locked)
creation_time, -- emptydate
0, -- canchangesubject
30, -- maxusers
1, -- publicroom
0, -- moderated
0, -- membersonly
0, -- caninvite
NULL, -- roompassword
1, -- candiscoverjid
1, -- logenabled
'', -- subject
7, -- rolestobroadcast
0, -- usereservednick
1, -- canchangenick
1, -- canregister
0, -- allowpm
0, -- fmucenabled
NULL, -- fmucoutboundnode
NULL, -- fmucoutboundmode
NULL -- fmucinboundnodes
);
IF i % 10 = 0 THEN
RAISE NOTICE 'Created room: %', room_name;
END IF;
END LOOP;
RAISE NOTICE 'Room creation complete.';
END $$;
-- Now redistribute messages across all 50 rooms
-- This simulates a more realistic distribution where each room has messages
DO $$
BEGIN
RAISE NOTICE 'Redistributing messages across all 50 rooms...';
UPDATE ofmucconversationlog
SET roomid = (messageid % 50) + 1;
RAISE NOTICE 'Message redistribution complete.';
END $$;
-- Verify
SELECT 'Total rooms: ' || COUNT(*)::TEXT AS result FROM ofmucroom;
SELECT 'Total messages: ' || COUNT(*)::TEXT AS result FROM ofmucconversationlog;
SELECT 'Messages per room (sample):' AS result;
SELECT 'Room ' || roomid || ': ' || COUNT(*)::TEXT || ' messages' AS result
FROM ofmucconversationlog
GROUP BY roomid
ORDER BY roomid
LIMIT 10;

View File

@ -1,25 +1,29 @@
-- =============================================================================
-- Generate Test Data: Slow Startup Issue Recreation
-- Generate Test Messages (~410,000) - PostgreSQL
-- =============================================================================
--
-- Compatibility: all deployments (simple, cluster, federation, cluster_with_federation, proxy)
-- Database: PostgreSQL
-- Compatibility: All PostgreSQL deployments (simple, cluster, federation, etc.)
--
-- Purpose:
-- Generates ~410,000 MUC messages to simulate a long-running environment
-- experiencing slow startup due to large message history.
-- Generates ~410,000 MUC messages distributed across 2 rooms to simulate a
-- long-running environment experiencing slow startup due to large message
-- history. Useful for testing MUC history loading performance.
--
-- Prerequisites:
-- - Rooms with IDs 1 and 2 must exist (messages alternate between them)
-- - Use with 000-init-openfire.sql which creates default rooms
--
-- Usage:
-- 1. Copy this file to your deployment's sql/ directory:
--
-- cp optional/sql/001-generate-test-data.sql simple/sql/
--
-- 2. Restart containers (or start fresh if DB already initialised):
-- Option 1 - Copy to deployment's sql/ directory (runs on container start):
--
-- cp optional/sql/postgresql/generate-test-messages.sql simple/sql/001-generate-test-messages.sql
-- ./start.sh
--
-- Alternatively, run manually against a running database:
-- Option 2 - Run manually against a running database:
--
-- docker exec -i simple-db-1 psql -U openfire -d openfire < optional/sql/001-generate-test-data.sql
-- docker exec -i simple-db-1 psql -U openfire -d openfire \
-- < optional/sql/postgresql/generate-test-messages.sql
--
-- =============================================================================

View File

@ -0,0 +1,128 @@
-- =============================================================================
-- Performance Test: 10,000 Minimal MUC Rooms - PostgreSQL
-- =============================================================================
--
-- Database: PostgreSQL
-- Compatibility: All PostgreSQL deployments (simple, cluster, federation, etc.)
--
-- Purpose:
-- Creates 10,000 MUC rooms with minimal data for testing parallel loading
-- performance at scale. Each room includes:
-- - Basic room metadata
-- - Single owner affiliation
-- - No message history (focus on room loading, not history)
--
-- This is ideal for testing MUC room loading performance when you need many
-- rooms but don't need message history to slow things down.
--
-- Note:
-- This script replaces any existing rooms (uses room IDs 1-10000).
-- For a smaller, more realistic dataset with messages and affiliations,
-- see performance-test-200-rooms-with-data.sql instead.
--
-- Usage:
-- Option 1 - Copy to deployment's sql/ directory (runs on container start):
--
-- cp optional/sql/postgresql/performance-test-10000-rooms.sql simple/sql/001-perf-rooms.sql
-- ./start.sh
--
-- Option 2 - Run manually against a running database:
--
-- docker exec -i simple-db-1 psql -U openfire -d openfire \
-- < optional/sql/postgresql/performance-test-10000-rooms.sql
--
-- =============================================================================
DO $$
DECLARE
base_time BIGINT := (EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT;
batch_size INTEGER := 1000;
i INTEGER;
BEGIN
RAISE NOTICE 'Creating 10,000 performance test MUC rooms...';
RAISE NOTICE 'Current time (ms): %', base_time;
RAISE NOTICE 'Using batch inserts for efficiency...';
-- Create rooms 1 through 10,000 using generate_series for efficiency
-- Insert rooms in batches to avoid memory issues
FOR i IN 0..9 LOOP
INSERT INTO ofmucroom (
serviceid, roomid, creationdate, modificationdate, name, naturalname, description,
lockeddate, emptydate, canchangesubject, maxusers, publicroom, moderated,
membersonly, caninvite, roompassword, candiscoverjid, logenabled,
subject, rolestobroadcast,
usereservednick, canchangenick, canregister, allowpm, fmucenabled,
fmucoutboundnode, fmucoutboundmode, fmucinboundnodes
)
SELECT
1, -- serviceid
room_num, -- roomid
LPAD((base_time - (room_num * 10000))::TEXT, 15, '0'), -- creationdate
LPAD((base_time - (room_num * 10000))::TEXT, 15, '0'), -- modificationdate
'perftest' || room_num::TEXT, -- name
'Performance Test Room ' || room_num::TEXT, -- naturalname
'Test room for parallel loading performance testing', -- description
'000000000000000', -- lockeddate (not locked)
LPAD((base_time - (room_num * 10000))::TEXT, 15, '0'), -- emptydate
1, -- canchangesubject
50, -- maxusers
1, -- publicroom
0, -- moderated
0, -- membersonly
1, -- caninvite
NULL, -- roompassword
1, -- candiscoverjid
1, -- logenabled
'Welcome to performance test room ' || room_num::TEXT, -- subject
7, -- rolestobroadcast (all roles)
0, -- usereservednick
1, -- canchangenick
1, -- canregister
1, -- allowpm (anyone)
0, -- fmucenabled
NULL, -- fmucoutboundnode
NULL, -- fmucoutboundmode
NULL -- fmucinboundnodes
FROM generate_series((i * batch_size) + 1, (i + 1) * batch_size) AS room_num;
RAISE NOTICE 'Batch %: Inserted rooms % to %', i + 1, (i * batch_size) + 1, (i + 1) * batch_size;
END LOOP;
RAISE NOTICE 'Room creation complete. Creating affiliations...';
-- Create owner affiliations in batches (one owner per room)
FOR i IN 0..9 LOOP
INSERT INTO ofmucaffiliation (roomid, jid, affiliation)
SELECT
room_num,
'owner' || room_num::TEXT || '@xmpp.localhost.example',
10 -- owner affiliation
FROM generate_series((i * batch_size) + 1, (i + 1) * batch_size) AS room_num;
RAISE NOTICE 'Batch %: Created affiliations for rooms % to %', i + 1, (i * batch_size) + 1, (i + 1) * batch_size;
END LOOP;
RAISE NOTICE 'Performance test room creation complete.';
RAISE NOTICE 'Total rooms created: 10,000';
RAISE NOTICE 'Total affiliations created: %', (SELECT COUNT(*) FROM ofmucaffiliation WHERE roomid BETWEEN 1 AND 10000);
END $$;
-- Set history configuration for the service
INSERT INTO ofmucserviceprop (serviceid, name, propvalue)
VALUES (1, 'history.maxNumber', '100')
ON CONFLICT (serviceid, name) DO UPDATE SET propvalue = '100';
INSERT INTO ofmucserviceprop (serviceid, name, propvalue)
VALUES (1, 'history.type', 'number')
ON CONFLICT (serviceid, name) DO UPDATE SET propvalue = 'number';
-- Verify data
SELECT 'Total rooms: ' || COUNT(*)::TEXT AS summary FROM ofmucroom;
SELECT 'Total affiliations: ' || COUNT(*)::TEXT AS summary FROM ofmucaffiliation;
SELECT 'Total messages: ' || COUNT(*)::TEXT AS summary FROM ofmucconversationlog;
SELECT 'Sample - Messages per room (first 10):' AS summary;
SELECT 'Room ' || roomid || ': ' || COUNT(*)::TEXT || ' messages' AS detail
FROM ofmucconversationlog
WHERE roomid <= 10
GROUP BY roomid
ORDER BY roomid;

View File

@ -0,0 +1,164 @@
-- =============================================================================
-- Performance Test: 200 Rooms with Realistic Data - PostgreSQL
-- =============================================================================
--
-- Database: PostgreSQL
-- Compatibility: All PostgreSQL deployments (simple, cluster, federation, etc.)
--
-- Purpose:
-- Creates 200 MUC rooms with realistic data for testing parallel loading
-- performance. Each room includes:
-- - Varied affiliations (1 owner, 1-2 admins, 3-5 members)
-- - Message history (100-500 messages per room, ~60,000 total)
-- - Realistic metadata
--
-- This is ideal when you need a realistic dataset with varied affiliations
-- and message history to test how Openfire handles loading complete room data.
--
-- Note:
-- This script replaces any existing rooms (uses room IDs 1-200).
-- For high-volume room testing without message history, see
-- performance-test-10000-rooms.sql instead.
--
-- Usage:
-- Option 1 - Copy to deployment's sql/ directory (runs on container start):
--
-- cp optional/sql/postgresql/performance-test-200-rooms-with-data.sql simple/sql/001-perf-rooms.sql
-- ./start.sh
--
-- Option 2 - Run manually against a running database:
--
-- docker exec -i simple-db-1 psql -U openfire -d openfire \
-- < optional/sql/postgresql/performance-test-200-rooms-with-data.sql
--
-- =============================================================================
DO $$
DECLARE
i INTEGER;
j INTEGER;
room_name VARCHAR(50);
creation_time CHAR(15);
base_time BIGINT := (EXTRACT(EPOCH FROM NOW()) * 1000)::BIGINT;
msg_id INTEGER := 1000000;
room_id_val INTEGER;
message_count INTEGER;
affiliation_count INTEGER;
BEGIN
RAISE NOTICE 'Creating 200 performance test MUC rooms...';
RAISE NOTICE 'Current time (ms): %', base_time;
-- Create rooms 1 through 200
FOR i IN 1..200 LOOP
room_name := 'perftest' || i::TEXT;
creation_time := LPAD((base_time - (i * 10000))::TEXT, 15, '0');
INSERT INTO ofmucroom (
serviceid, roomid, creationdate, modificationdate, name, naturalname, description,
lockeddate, emptydate, canchangesubject, maxusers, publicroom, moderated,
membersonly, caninvite, roompassword, candiscoverjid, logenabled,
subject, rolestobroadcast,
usereservednick, canchangenick, canregister, allowpm, fmucenabled,
fmucoutboundnode, fmucoutboundmode, fmucinboundnodes
)
VALUES (
1, -- serviceid
i, -- roomid
creation_time, -- creationdate
creation_time, -- modificationdate
room_name, -- name
'Performance Test Room ' || i::TEXT, -- naturalname
'Test room for parallel loading performance testing', -- description
'000000000000000', -- lockeddate (not locked)
creation_time, -- emptydate
1, -- canchangesubject
50, -- maxusers
1, -- publicroom
0, -- moderated
0, -- membersonly
1, -- caninvite
NULL, -- roompassword
1, -- candiscoverjid
1, -- logenabled
'Welcome to performance test room ' || i::TEXT, -- subject
7, -- rolestobroadcast (all roles)
0, -- usereservednick
1, -- canchangenick
1, -- canregister
1, -- allowpm (anyone)
0, -- fmucenabled
NULL, -- fmucoutboundnode
NULL, -- fmucoutboundmode
NULL -- fmucinboundnodes
)
RETURNING roomid INTO room_id_val;
-- Add affiliations for this room
-- Each room gets: 1 owner, 1-2 admins, 3-5 members
affiliation_count := 3 + (i % 3); -- 3-5 affiliations per room
-- Owner
INSERT INTO ofmucaffiliation (roomid, jid, affiliation)
VALUES (room_id_val, 'owner' || i::TEXT || '@xmpp.localhost.example', 10);
-- Admin(s)
FOR j IN 1..(1 + (i % 2)) LOOP
INSERT INTO ofmucaffiliation (roomid, jid, affiliation)
VALUES (room_id_val, 'admin' || i::TEXT || '-' || j::TEXT || '@xmpp.localhost.example', 20);
END LOOP;
-- Members
FOR j IN 1..(3 + (i % 3)) LOOP
INSERT INTO ofmucaffiliation (roomid, jid, affiliation)
VALUES (room_id_val, 'member' || i::TEXT || '-' || j::TEXT || '@xmpp.localhost.example', 30);
END LOOP;
-- Add message history for this room
-- Each room gets 100-500 messages (varies by room number)
message_count := 100 + ((i * 37) % 401); -- Pseudo-random 100-500
FOR j IN 1..message_count LOOP
INSERT INTO ofmucconversationlog (roomid, messageid, sender, nickname, logtime, subject, body, stanza)
VALUES (
room_id_val,
msg_id,
'user' || ((j % 10) + 1)::TEXT || '@xmpp.localhost.example/resource',
'User ' || ((j % 10) + 1)::TEXT,
LPAD((base_time - (j::BIGINT * 60000))::TEXT, 15, '0'), -- 1 minute intervals
CASE WHEN j % 50 = 1 THEN 'Discussion topic ' || (j/50 + 1)::TEXT ELSE NULL END,
'Test message ' || j::TEXT || ' in room ' || room_name,
NULL
);
msg_id := msg_id + 1;
END LOOP;
IF i % 20 = 0 THEN
RAISE NOTICE 'Created room % with % affiliations and % messages', room_name, affiliation_count, message_count;
END IF;
END LOOP;
RAISE NOTICE 'Performance test room creation complete.';
RAISE NOTICE 'Total rooms created: 200';
RAISE NOTICE 'Total affiliations created: %', (SELECT COUNT(*) FROM ofmucaffiliation);
RAISE NOTICE 'Total messages created: %', (SELECT COUNT(*) FROM ofmucconversationlog);
END $$;
-- Set history configuration for the service
INSERT INTO ofmucserviceprop (serviceid, name, propvalue)
VALUES (1, 'history.maxNumber', '100')
ON CONFLICT (serviceid, name) DO UPDATE SET propvalue = '100';
INSERT INTO ofmucserviceprop (serviceid, name, propvalue)
VALUES (1, 'history.type', 'number')
ON CONFLICT (serviceid, name) DO UPDATE SET propvalue = 'number';
-- Verify data
SELECT 'Total rooms: ' || COUNT(*)::TEXT AS summary FROM ofmucroom;
SELECT 'Total affiliations: ' || COUNT(*)::TEXT AS summary FROM ofmucaffiliation;
SELECT 'Total messages: ' || COUNT(*)::TEXT AS summary FROM ofmucconversationlog;
SELECT 'Sample - Messages per room (first 10):' AS summary;
SELECT 'Room ' || roomid || ': ' || COUNT(*)::TEXT || ' messages' AS detail
FROM ofmucconversationlog
WHERE roomid <= 10
GROUP BY roomid
ORDER BY roomid;

View File

@ -0,0 +1,44 @@
-- =============================================================================
-- Set MUC Room Loading Worker Count - PostgreSQL
-- =============================================================================
--
-- Database: PostgreSQL
-- Compatibility: All PostgreSQL deployments (simple, cluster, federation, etc.)
--
-- Purpose:
-- Sets the xmpp.muc.loading.workers property in the database.
-- This controls how many parallel workers are used to load MUC rooms
-- from the database during Openfire startup.
--
-- Usage:
-- -- For sequential loading (1 worker):
-- docker exec -i openfire-db-1 psql -U openfire -d openfire <<EOF
-- DELETE FROM ofproperty WHERE name = 'xmpp.muc.loading.workers';
-- INSERT INTO ofproperty (name, propvalue) VALUES ('xmpp.muc.loading.workers', '1');
-- EOF
--
-- -- For parallel loading (3 workers):
-- docker exec -i openfire-db-1 psql -U openfire -d openfire <<EOF
-- DELETE FROM ofproperty WHERE name = 'xmpp.muc.loading.workers';
-- INSERT INTO ofproperty (name, propvalue) VALUES ('xmpp.muc.loading.workers', '3');
-- EOF
--
-- -- For parallel loading (5 workers):
-- docker exec -i openfire-db-1 psql -U openfire -d openfire <<EOF
-- DELETE FROM ofproperty WHERE name = 'xmpp.muc.loading.workers';
-- INSERT INTO ofproperty (name, propvalue) VALUES ('xmpp.muc.loading.workers', '5');
-- EOF
--
-- Note: The value will be read during Openfire startup, so you need to
-- restart Openfire after changing this property.
--
-- =============================================================================
-- This file is a template - actual values are set dynamically by the test script
-- Default to 1 worker (sequential) if run standalone
DELETE FROM ofproperty WHERE name = 'xmpp.muc.loading.workers';
INSERT INTO ofproperty (name, propvalue) VALUES ('xmpp.muc.loading.workers', '1');
SELECT 'Property set: ' || name || ' = ' || propvalue AS result
FROM ofproperty
WHERE name = 'xmpp.muc.loading.workers';