mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:51:13 -05:00
Fix build errors in system activity service
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
✅ **Migration Complete** - The relational versioning system is now active. This guide documents the migration for reference.
|
✅ **Migration Complete** - The relational versioning system is now fully active. Legacy system has been removed.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@@ -25,72 +25,53 @@ The new system uses dedicated relational tables:
|
|||||||
1. **Phase 1: Create relational tables** ✅ Complete
|
1. **Phase 1: Create relational tables** ✅ Complete
|
||||||
2. **Phase 2: Enable triggers** ✅ Complete
|
2. **Phase 2: Enable triggers** ✅ Complete
|
||||||
3. **Phase 3: Dual-write period** ✅ Complete
|
3. **Phase 3: Dual-write period** ✅ Complete
|
||||||
4. **Phase 4: Backfill historical data** ⏸️ Optional
|
4. **Phase 4: Archive legacy data** ✅ Complete
|
||||||
5. **Phase 5: Monitor** 🔄 Ongoing
|
5. **Phase 5: Drop legacy tables & functions** ✅ Complete
|
||||||
6. **Phase 6: Deprecate JSONB table** 📅 Future
|
6. **Phase 6: Update documentation & code** ✅ Complete
|
||||||
|
|
||||||
## Current State
|
## Current State
|
||||||
|
|
||||||
- ✅ All new versions written to relational tables
|
- ✅ All versions written to relational tables
|
||||||
- ✅ Triggers active on all entity tables
|
- ✅ Triggers active on all entity tables
|
||||||
- ✅ Automated cleanup scheduled via pg_cron
|
- ✅ Automated cleanup scheduled via pg_cron
|
||||||
- ⚠️ Old `entity_versions` table retained for backward compatibility
|
- ✅ Old `entity_versions` table archived to `entity_versions_archive`
|
||||||
- ⚠️ `src/lib/versioningHelpers.ts` deprecated but not removed (scheduled for removal: 2025-12-01)
|
- ✅ Legacy JSONB tables and functions removed
|
||||||
|
- ✅ `src/lib/versioningHelpers.ts` removed
|
||||||
|
- ✅ All code updated to use relational system
|
||||||
|
|
||||||
## Migration Timeline
|
## Completed Migration Phases
|
||||||
|
|
||||||
### ✅ Phase 1: New System Deployed (Completed)
|
### ✅ Phase 1: New System Deployed
|
||||||
- Relational version tables created (`park_versions`, `ride_versions`, etc.)
|
- Relational version tables created (`park_versions`, `ride_versions`, etc.)
|
||||||
- Triggers enabled on all entity tables
|
- Triggers enabled on all entity tables
|
||||||
- RLS policies active and tested
|
- RLS policies active and tested
|
||||||
- Frontend integrated with new hooks
|
- Frontend integrated with new hooks
|
||||||
- Complete documentation suite created
|
- Complete documentation suite created
|
||||||
|
|
||||||
### 🟡 Phase 2: Parallel Operation (Current - Days 1-30)
|
### ✅ Phase 2: Parallel Operation
|
||||||
- Both old and new systems exist side-by-side
|
- Both old and new systems existed side-by-side
|
||||||
- New triggers create versions in relational tables
|
- New triggers created versions in relational tables
|
||||||
- Old JSONB table receives no new data
|
- Old JSONB table received no new data
|
||||||
- Monitoring for issues and edge cases
|
- Monitored for issues and edge cases
|
||||||
- `versioningHelpers.ts` marked as deprecated
|
|
||||||
|
|
||||||
**Action Items:**
|
### ✅ Phase 3: Archive Legacy Data
|
||||||
- [ ] Monitor version creation in new tables
|
- Archived old `entity_versions` to `entity_versions_archive`
|
||||||
- [ ] Verify no new inserts to old `entity_versions` table
|
- Verified data integrity and counts matched
|
||||||
- [ ] Search codebase for deprecated function usage
|
- Archive table retained for audit purposes
|
||||||
- [ ] Collect feedback from team
|
|
||||||
|
|
||||||
### 🔵 Phase 3: Archive Legacy Data (Day 30)
|
### ✅ Phase 4: Drop Legacy System
|
||||||
- Archive old `entity_versions` to `entity_versions_archive`
|
- Dropped old `entity_versions` table
|
||||||
- Verify data integrity and counts match
|
- Dropped old RPC functions (`create_entity_version`, `compare_versions`, etc.)
|
||||||
- Keep archive for 60 more days as safety net
|
- Dropped `auto_create_entity_version()` trigger function
|
||||||
- Document archive location and access procedures
|
- Removed `src/lib/versioningHelpers.ts` file
|
||||||
|
- Updated all code to use relational system only
|
||||||
|
- Updated documentation
|
||||||
|
|
||||||
**SQL Migration:**
|
### 🔄 Phase 5: Ongoing Optimization
|
||||||
```sql
|
- Automated cleanup via pg_cron runs monthly
|
||||||
-- See supabase/migrations/*_archive_legacy_versions.sql
|
- Performance monitoring and index tuning as needed
|
||||||
CREATE TABLE entity_versions_archive (LIKE entity_versions INCLUDING ALL);
|
|
||||||
INSERT INTO entity_versions_archive SELECT * FROM entity_versions;
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🟢 Phase 4: Drop Legacy Tables (Day 90)
|
|
||||||
- Drop old `entity_versions` table
|
|
||||||
- Drop old RPC functions (`create_entity_version`, `compare_versions`, etc.)
|
|
||||||
- Remove `src/lib/versioningHelpers.ts` file
|
|
||||||
- Remove archive table (or retain indefinitely for audit)
|
|
||||||
- Update all documentation to remove references to old system
|
|
||||||
|
|
||||||
**SQL Migration:**
|
|
||||||
```sql
|
|
||||||
-- See supabase/migrations/*_drop_legacy_versions.sql
|
|
||||||
DROP TABLE entity_versions CASCADE;
|
|
||||||
DROP FUNCTION create_entity_version(...);
|
|
||||||
```
|
|
||||||
|
|
||||||
### 🚀 Phase 5: Optimization (Ongoing)
|
|
||||||
- Automated cleanup via pg_cron (monthly)
|
|
||||||
- Performance monitoring and index tuning
|
|
||||||
- Documentation updates based on usage patterns
|
- Documentation updates based on usage patterns
|
||||||
- Version retention policy adjustments as needed
|
- Version retention policy: 50 versions per entity (configurable)
|
||||||
|
|
||||||
## Backfill Script (Optional)
|
## Backfill Script (Optional)
|
||||||
|
|
||||||
@@ -134,27 +115,31 @@ WHERE ev.entity_type = 'park'
|
|||||||
ON CONFLICT DO NOTHING;
|
ON CONFLICT DO NOTHING;
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cleanup (Future)
|
## What Was Removed
|
||||||
|
|
||||||
When ready to fully deprecate JSONB system:
|
The following tables, functions, and files have been permanently removed:
|
||||||
|
|
||||||
```sql
|
**Tables:**
|
||||||
-- 1. Verify all versions migrated
|
- `entity_versions` (main JSONB table)
|
||||||
SELECT COUNT(*) FROM entity_versions; -- Should match relational tables
|
- `entity_field_history` (field-level change tracking)
|
||||||
|
- `entity_relationships_history` (relationship tracking)
|
||||||
|
- `version_diffs` (pre-computed diffs)
|
||||||
|
|
||||||
-- 2. Drop old table (IRREVERSIBLE)
|
**Functions:**
|
||||||
DROP TABLE IF EXISTS entity_versions CASCADE;
|
- `create_entity_version()` - Created JSONB versions
|
||||||
|
- `compare_versions()` - Compared JSONB versions
|
||||||
|
- `create_field_history_entries()` - Created field history
|
||||||
|
- `auto_create_entity_version()` - Automatic versioning trigger
|
||||||
|
|
||||||
-- 3. Remove deprecated helpers
|
**Files:**
|
||||||
-- Delete src/lib/versioningHelpers.ts
|
- `src/lib/versioningHelpers.ts` - Old helper functions
|
||||||
```
|
|
||||||
|
|
||||||
## Rollback Plan
|
**Archived:**
|
||||||
|
- `entity_versions_archive` - Contains historical JSONB data for audit purposes
|
||||||
|
|
||||||
If issues arise, rollback steps:
|
## Field-Level History
|
||||||
|
|
||||||
1. Disable triggers on entity tables
|
Field-level history tracking (`entity_field_history` table) has been removed. To view field changes:
|
||||||
2. Revert edge functions to use old JSONB system
|
- Use the **Version Comparison** feature in the Version History tab
|
||||||
3. Keep relational tables for future retry
|
- Compare any two versions to see all field-level changes
|
||||||
|
- The `FieldHistoryDialog` component now shows a helpful message directing users to version comparison
|
||||||
**Note:** Not recommended - new system is production-ready.
|
|
||||||
|
|||||||
@@ -137,19 +137,20 @@ export async function fetchSystemActivities(
|
|||||||
// Process park versions
|
// Process park versions
|
||||||
if (!parkVersions.error && parkVersions.data) {
|
if (!parkVersions.error && parkVersions.data) {
|
||||||
for (const version of parkVersions.data) {
|
for (const version of parkVersions.data) {
|
||||||
|
const parkVersion = version as any; // Type assertion for relational version structure
|
||||||
activities.push({
|
activities.push({
|
||||||
id: version.version_id,
|
id: parkVersion.version_id,
|
||||||
type: 'entity_change',
|
type: 'entity_change',
|
||||||
timestamp: version.created_at,
|
timestamp: parkVersion.created_at,
|
||||||
actor_id: version.created_by || null,
|
actor_id: parkVersion.created_by || null,
|
||||||
action: `${version.change_type} park`,
|
action: `${parkVersion.change_type} park`,
|
||||||
details: {
|
details: {
|
||||||
entity_type: 'park',
|
entity_type: 'park',
|
||||||
entity_id: version.park_id,
|
entity_id: parkVersion.park_id,
|
||||||
entity_name: version.name,
|
entity_name: parkVersion.name,
|
||||||
change_type: version.change_type,
|
change_type: parkVersion.change_type,
|
||||||
change_reason: version.change_reason,
|
change_reason: parkVersion.change_reason,
|
||||||
version_number: version.version_number,
|
version_number: parkVersion.version_number,
|
||||||
} as EntityChangeDetails,
|
} as EntityChangeDetails,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -158,19 +159,20 @@ export async function fetchSystemActivities(
|
|||||||
// Process ride versions
|
// Process ride versions
|
||||||
if (!rideVersions.error && rideVersions.data) {
|
if (!rideVersions.error && rideVersions.data) {
|
||||||
for (const version of rideVersions.data) {
|
for (const version of rideVersions.data) {
|
||||||
|
const rideVersion = version as any;
|
||||||
activities.push({
|
activities.push({
|
||||||
id: version.version_id,
|
id: rideVersion.version_id,
|
||||||
type: 'entity_change',
|
type: 'entity_change',
|
||||||
timestamp: version.created_at,
|
timestamp: rideVersion.created_at,
|
||||||
actor_id: version.created_by || null,
|
actor_id: rideVersion.created_by || null,
|
||||||
action: `${version.change_type} ride`,
|
action: `${rideVersion.change_type} ride`,
|
||||||
details: {
|
details: {
|
||||||
entity_type: 'ride',
|
entity_type: 'ride',
|
||||||
entity_id: version.ride_id,
|
entity_id: rideVersion.ride_id,
|
||||||
entity_name: version.name,
|
entity_name: rideVersion.name,
|
||||||
change_type: version.change_type,
|
change_type: rideVersion.change_type,
|
||||||
change_reason: version.change_reason,
|
change_reason: rideVersion.change_reason,
|
||||||
version_number: version.version_number,
|
version_number: rideVersion.version_number,
|
||||||
} as EntityChangeDetails,
|
} as EntityChangeDetails,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -179,19 +181,20 @@ export async function fetchSystemActivities(
|
|||||||
// Process company versions
|
// Process company versions
|
||||||
if (!companyVersions.error && companyVersions.data) {
|
if (!companyVersions.error && companyVersions.data) {
|
||||||
for (const version of companyVersions.data) {
|
for (const version of companyVersions.data) {
|
||||||
|
const companyVersion = version as any;
|
||||||
activities.push({
|
activities.push({
|
||||||
id: version.version_id,
|
id: companyVersion.version_id,
|
||||||
type: 'entity_change',
|
type: 'entity_change',
|
||||||
timestamp: version.created_at,
|
timestamp: companyVersion.created_at,
|
||||||
actor_id: version.created_by || null,
|
actor_id: companyVersion.created_by || null,
|
||||||
action: `${version.change_type} company`,
|
action: `${companyVersion.change_type} company`,
|
||||||
details: {
|
details: {
|
||||||
entity_type: 'company',
|
entity_type: 'company',
|
||||||
entity_id: version.company_id,
|
entity_id: companyVersion.company_id,
|
||||||
entity_name: version.name,
|
entity_name: companyVersion.name,
|
||||||
change_type: version.change_type,
|
change_type: companyVersion.change_type,
|
||||||
change_reason: version.change_reason,
|
change_reason: companyVersion.change_reason,
|
||||||
version_number: version.version_number,
|
version_number: companyVersion.version_number,
|
||||||
} as EntityChangeDetails,
|
} as EntityChangeDetails,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -200,19 +203,20 @@ export async function fetchSystemActivities(
|
|||||||
// Process ride model versions
|
// Process ride model versions
|
||||||
if (!modelVersions.error && modelVersions.data) {
|
if (!modelVersions.error && modelVersions.data) {
|
||||||
for (const version of modelVersions.data) {
|
for (const version of modelVersions.data) {
|
||||||
|
const modelVersion = version as any;
|
||||||
activities.push({
|
activities.push({
|
||||||
id: version.version_id,
|
id: modelVersion.version_id,
|
||||||
type: 'entity_change',
|
type: 'entity_change',
|
||||||
timestamp: version.created_at,
|
timestamp: modelVersion.created_at,
|
||||||
actor_id: version.created_by || null,
|
actor_id: modelVersion.created_by || null,
|
||||||
action: `${version.change_type} ride_model`,
|
action: `${modelVersion.change_type} ride_model`,
|
||||||
details: {
|
details: {
|
||||||
entity_type: 'ride_model',
|
entity_type: 'ride_model',
|
||||||
entity_id: version.ride_model_id,
|
entity_id: modelVersion.ride_model_id,
|
||||||
entity_name: version.name,
|
entity_name: modelVersion.name,
|
||||||
change_type: version.change_type,
|
change_type: modelVersion.change_type,
|
||||||
change_reason: version.change_reason,
|
change_reason: modelVersion.change_reason,
|
||||||
version_number: version.version_number,
|
version_number: modelVersion.version_number,
|
||||||
} as EntityChangeDetails,
|
} as EntityChangeDetails,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,14 +50,18 @@ export default function AdminDashboard() {
|
|||||||
const checkSuspiciousVersions = useCallback(async () => {
|
const checkSuspiciousVersions = useCallback(async () => {
|
||||||
if (!user || !isModerator()) return;
|
if (!user || !isModerator()) return;
|
||||||
|
|
||||||
const { count, error } = await supabase
|
// Query all version tables for suspicious entries (no changed_by)
|
||||||
.from('entity_versions')
|
const queries = [
|
||||||
.select('*', { count: 'exact', head: true })
|
supabase.from('park_versions').select('*', { count: 'exact', head: true }).is('created_by', null),
|
||||||
.is('changed_by', null);
|
supabase.from('ride_versions').select('*', { count: 'exact', head: true }).is('created_by', null),
|
||||||
|
supabase.from('company_versions').select('*', { count: 'exact', head: true }).is('created_by', null),
|
||||||
|
supabase.from('ride_model_versions').select('*', { count: 'exact', head: true }).is('created_by', null),
|
||||||
|
];
|
||||||
|
|
||||||
if (!error && count !== null) {
|
const results = await Promise.all(queries);
|
||||||
setSuspiciousVersionsCount(count);
|
const totalCount = results.reduce((sum, result) => sum + (result.count || 0), 0);
|
||||||
}
|
|
||||||
|
setSuspiciousVersionsCount(totalCount);
|
||||||
}, [user, isModerator]);
|
}, [user, isModerator]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- Drop legacy versioning function that references deleted tables
|
||||||
|
-- This function calls create_entity_version() which was removed in the previous migration
|
||||||
|
DROP FUNCTION IF EXISTS public.auto_create_entity_version() CASCADE;
|
||||||
Reference in New Issue
Block a user