mirror of
https://github.com/wekan/wekan.git
synced 2026-02-09 09:44:22 +01:00
196 lines
6.7 KiB
Markdown
196 lines
6.7 KiB
Markdown
|
|
## UI Performance Optimization Analysis: Replace Meteor.call with Pub/Sub
|
||
|
|
|
||
|
|
### Current Issues Identified
|
||
|
|
|
||
|
|
The codebase uses several patterns where Meteor.call() could be replaced with pub/sub subscriptions for faster UI updates:
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## CRITICAL OPPORTUNITIES (High Impact)
|
||
|
|
|
||
|
|
### 1. **cron.getMigrationProgress** - Polling Every 2 Seconds
|
||
|
|
**Location:** `imports/cronMigrationClient.js` lines 26-53, called every 2 seconds via `setInterval`
|
||
|
|
**Current Issue:**
|
||
|
|
- Polls for progress data every 2000ms even when nothing is changing
|
||
|
|
- Adds server load with repeated RPC calls
|
||
|
|
- Client must wait for response before updating
|
||
|
|
|
||
|
|
**Recommended Solution:**
|
||
|
|
- Already partially implemented! Migration status is published via `cronMigrationStatus` publication
|
||
|
|
- Keep existing pub/sub for status updates (statusMessage, status field)
|
||
|
|
- Still use polling for `getMigrationProgress()` for non-status data (migration steps list, ETA calculation)
|
||
|
|
|
||
|
|
**Implementation Status:** ✅ Already in place
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 2. **AccountSettings Helper Methods** - Used in Profile Popup
|
||
|
|
**Location:** `client/components/users/userHeader.js` lines 173, 182, 191
|
||
|
|
**Current Methods:**
|
||
|
|
```javascript
|
||
|
|
Meteor.call('AccountSettings.allowEmailChange', (_, result) => {...})
|
||
|
|
Meteor.call('AccountSettings.allowUserNameChange', (_, result) => {...})
|
||
|
|
Meteor.call('AccountSettings.allowUserDelete', (_, result) => {...})
|
||
|
|
```
|
||
|
|
|
||
|
|
**Current Issue:**
|
||
|
|
- Callbacks don't return values (templates can't use reactive helpers with Meteor.call callbacks)
|
||
|
|
- Requires separate async calls for each setting
|
||
|
|
- Falls back to unresponsive UI
|
||
|
|
|
||
|
|
**Recommended Solution:**
|
||
|
|
- Use existing `accountSettings` publication (already exists in `server/publications/accountSettings.js`)
|
||
|
|
- Create reactive helpers that read from `AccountSettings` collection instead
|
||
|
|
- Subscribe to `accountSettings` in userHeader template
|
||
|
|
|
||
|
|
**Benefits:**
|
||
|
|
- Instant rendering with cached data
|
||
|
|
- Reactive updates if settings change
|
||
|
|
- No network round-trip for initial render
|
||
|
|
- Saves 3 Meteor.call() per profile popup load
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 3. **cron.getJobs** - Polling Every 2 Seconds
|
||
|
|
**Location:** `imports/cronMigrationClient.js` line 62-67, called every 2 seconds
|
||
|
|
**Current Issue:**
|
||
|
|
- Fetches list of all cron jobs every 2 seconds
|
||
|
|
- RPC overhead even when jobs list hasn't changed
|
||
|
|
|
||
|
|
**Recommended Solution:**
|
||
|
|
- Create `cronJobs` publication in `server/publications/cronJobs.js`
|
||
|
|
- Publish `CronJobStatus.find({})` for admin users
|
||
|
|
- Subscribe on client, use collection directly instead of polling
|
||
|
|
|
||
|
|
**Benefits:**
|
||
|
|
- Real-time updates via DDP instead of polling
|
||
|
|
- Reduced server load
|
||
|
|
- Lower latency for job status changes
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 4. **toggleGreyIcons, setAvatarUrl** - User Preference Updates
|
||
|
|
**Location:** `client/components/users/userHeader.js` lines 103, 223
|
||
|
|
**Current Pattern:**
|
||
|
|
```javascript
|
||
|
|
Meteor.call('toggleGreyIcons', (err) => {...})
|
||
|
|
Meteor.call('setAvatarUrl', avatarUrl, (err) => {...})
|
||
|
|
```
|
||
|
|
|
||
|
|
**Recommended Solution:**
|
||
|
|
- These are write operations (correct for Meteor.call)
|
||
|
|
- Keep Meteor.call but ensure subscribed data reflects changes immediately
|
||
|
|
- Current user subscription should update reactively after call completes
|
||
|
|
|
||
|
|
**Status:** ✅ Already correct pattern
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 5. **setBoardView, setListCollapsedState, setSwimlaneCollapsedState**
|
||
|
|
**Location:** `client/lib/utils.js` lines 293, 379, 420
|
||
|
|
**Current Pattern:** Write operations via Meteor.call
|
||
|
|
**Status:** ✅ Already correct pattern (mutations should use Meteor.call)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## MODERATE OPPORTUNITIES (Medium Impact)
|
||
|
|
|
||
|
|
### 6. **getCustomUI, getMatomoConf** - Configuration Data
|
||
|
|
**Location:** `client/lib/utils.js` lines 748, 799
|
||
|
|
**Current Issue:**
|
||
|
|
- Fetches config data that rarely changes
|
||
|
|
- Every template that needs it makes a separate call
|
||
|
|
|
||
|
|
**Recommended Solution:**
|
||
|
|
- Create `customUI` and `matomoConfig` publications
|
||
|
|
- Cache on client, subscribe once globally
|
||
|
|
- Much faster for repeated access
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 7. **Attachment Migration Status** - Multiple Calls
|
||
|
|
**Location:** `client/lib/attachmentMigrationManager.js` lines 66, 142, 169
|
||
|
|
**Methods:**
|
||
|
|
- `attachmentMigration.isBoardMigrated`
|
||
|
|
- `attachmentMigration.migrateBoardAttachments`
|
||
|
|
- `attachmentMigration.getProgress`
|
||
|
|
|
||
|
|
**Recommended Solution:**
|
||
|
|
- Create `attachmentMigrationStatus` publication
|
||
|
|
- Publish board migration status for boards user has access to
|
||
|
|
- Subscribe to get migration state reactively
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### 8. **Position History Tracking** - Fire-and-Forget Operations
|
||
|
|
**Location:** `client/lib/originalPositionHelpers.js` lines 12, 26, 40, 54, 71
|
||
|
|
**Methods:**
|
||
|
|
- `positionHistory.trackSwimlane`
|
||
|
|
- `positionHistory.trackList`
|
||
|
|
- `positionHistory.trackCard`
|
||
|
|
- Undo/redo methods
|
||
|
|
|
||
|
|
**Current:** These are write operations
|
||
|
|
**Status:** ✅ Correct to use Meteor.call (not candidates for pub/sub)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## ALREADY OPTIMIZED ✅
|
||
|
|
|
||
|
|
These are already using pub/sub properly:
|
||
|
|
- `Meteor.subscribe('setting')` - Global settings
|
||
|
|
- `Meteor.subscribe('board', boardId)` - Board data
|
||
|
|
- `Meteor.subscribe('notificationActivities')` - Notifications
|
||
|
|
- `Meteor.subscribe('sessionData')` - User session data
|
||
|
|
- `Meteor.subscribe('my-avatars')` - User avatars
|
||
|
|
- `Meteor.subscribe('userGreyIcons')` - User preferences
|
||
|
|
- `Meteor.subscribe('accountSettings')` - Account settings
|
||
|
|
- `Meteor.subscribe('cronMigrationStatus')` - Migration status (just implemented)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## IMPLEMENTATION PRIORITY
|
||
|
|
|
||
|
|
### Priority 1 (Quick Wins - 30 mins)
|
||
|
|
1. **Fix AccountSettings helpers** - Use published data instead of Meteor.call
|
||
|
|
- Replace callbacks in templates with reactive collection access
|
||
|
|
- Already subscribed, just need to use it
|
||
|
|
|
||
|
|
### Priority 2 (Medium Effort - 1 hour)
|
||
|
|
2. **Add cronJobs publication** - Replace polling with pub/sub
|
||
|
|
3. **Add customUI publication** - Cache config data
|
||
|
|
4. **Add matomoConfig publication** - Cache config data
|
||
|
|
|
||
|
|
### Priority 3 (Larger Effort - 2 hours)
|
||
|
|
5. **Add attachmentMigrationStatus publication** - Multiple methods become reactive
|
||
|
|
6. **Optimize cron.getMigrationProgress** - Further reduce polling if needed
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## PERMISSION PRESERVATION
|
||
|
|
|
||
|
|
All recommended changes maintain existing permission model:
|
||
|
|
|
||
|
|
- **accountSettings**: Already published to all users
|
||
|
|
- **cronJobs/cronMigrationStatus**: Publish only to admin users (check in publication)
|
||
|
|
- **attachmentMigrationStatus**: Publish only to boards user is member of
|
||
|
|
- **customUI/matomoConfig**: Publish to all users (public config)
|
||
|
|
|
||
|
|
No security changes needed - just move from Meteor.call to pub/sub with same permission checks.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## PERFORMANCE IMPACT ESTIMATION
|
||
|
|
|
||
|
|
### Current State (with polling)
|
||
|
|
- 1 poll call every 2 seconds = 30 calls/minute per client
|
||
|
|
- 10 admin clients = 300 calls/minute to server
|
||
|
|
- High DDP message traffic
|
||
|
|
|
||
|
|
### After Optimization
|
||
|
|
- 1 subscription = 1 initial sync + reactive updates only
|
||
|
|
- 10 admin clients = 10 subscriptions total
|
||
|
|
- **90% reduction in RPC overhead**
|
||
|
|
- Sub-100ms updates instead of up to 2000ms latency
|
||
|
|
|