Skip to content

Conversation

@guyofeck
Copy link
Collaborator

Summary

  • Add WatchListManager class for maintaining sorted watch results on the client
  • Add createComparatorFromSort helper for creating sort comparators from strings
  • Export new utilities from package index

Features

  • Binary search insertion - O(log n) for maintaining sorted order
  • O(1) lookup by ID - Uses Map for fast lookups
  • Limit enforcement - Automatically truncates list when items exceed limit
  • Automatic re-sorting - Re-positions items when sort field changes

Usage

import { WatchListManager } from '@base44/sdk';

const manager = new WatchListManager<Task>({
  sort: '-created_date',
  limit: 10,
});

// Initialize with existing data
const tasks = await base44.entities.Task.filter({ status: 'active' });
manager.initialize(tasks.data);

// Handle watch events
const unsubscribe = base44.entities.Task.watch(
  { filter: { status: 'active' }, sort: '-created_date', limit: 10 },
  (event) => {
    const result = manager.handleEvent(event);
    if (result.added || result.removed || result.modified) {
      renderTaskList(manager.getItems());
    }
  }
);

Test plan

  • Unit tests for sort comparator creation
  • Unit tests for sorted insertions
  • Unit tests for limit enforcement
  • Unit tests for re-sorting on updates

Depends on: #86

Fixes #84

🤖 Generated with Claude Code

guyofeck and others added 2 commits January 22, 2026 23:05
This adds a watch() method to EntityHandler that allows subscribing to
filtered subsets of entities with real-time change notifications.

Features:
- watch(options, callback) method with filter, sort, fields, limit options
- WatchEvent with changeType ('added', 'modified', 'removed')
- subscribeQuery/unsubscribeQuery socket events for server communication
- Proper cleanup on unsubscribe

The watch() method differs from subscribe() in that:
- It supports filter, sort, fields, and limit options
- It returns changeType indicating how the change affects the filtered results
- It uses dedicated subscribe_query socket events

Example usage:
```typescript
const unsubscribe = base44.entities.Task.watch(
  { filter: { status: 'active' }, sort: '-created_date', limit: 10 },
  (event) => {
    if (event.changeType === 'added') {
      console.log('New matching task:', event.data);
    }
  }
);
```

Fixes #83

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This adds a utility class for maintaining a sorted list of entities from
watch() subscription events, optimizing for common operations like
insertions in sorted order and removals.

Features:
- WatchListManager class for managing sorted watch results
- createComparatorFromSort helper for creating sort comparators from strings
- Support for limit enforcement (truncates list to limit)
- Binary search insertion for O(log n) sorted insertions
- O(1) lookup by ID using Map
- Automatic re-sorting when sort field changes on update

Example usage:
```typescript
const manager = new WatchListManager<Task>({
  sort: '-created_date',
  limit: 10,
});

// Initialize with existing data
manager.initialize(await base44.entities.Task.filter({ status: 'active' }));

// Handle watch events
const unsubscribe = base44.entities.Task.watch(
  { filter: { status: 'active' }, sort: '-created_date', limit: 10 },
  (event) => {
    manager.handleEvent(event);
    renderTaskList(manager.getItems());
  }
);
```

Fixes #84

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@guyofeck guyofeck added the Live Query Live query subscription feature label Jan 22, 2026
@claude
Copy link

claude bot commented Jan 22, 2026

Claude finished @guyofeck's task —— View job


Pull Request Review: WatchListManager Implementation

I've completed my review of the WatchListManager implementation for client-side sorting optimization. Here's my comprehensive feedback:

Review Checklist

  • Read repository guidelines (CLAUDE.md)
  • Review WatchListManager implementation
  • Check sort comparator utility
  • Analyze entities module changes
  • Review test coverage
  • Assess performance implications
  • Check for security concerns
  • Provide overall feedback

Overall Assessment

The implementation is well-designed and provides a solid foundation for client-side sorting optimization of watch subscriptions. The code is clean, well-documented, and includes comprehensive test coverage.

Code Quality and Best Practices ✅

Strengths:

  • Excellent documentation with clear JSDoc comments and usage examples
  • Proper TypeScript typing throughout the codebase
  • Clean separation of concerns with focused methods
  • Good error handling (graceful null/undefined handling in comparator)
  • Consistent coding style

Minor Suggestions:

  • Consider adding type guards or validation for the getId function to ensure it returns a valid string
  • The handleEvent method could benefit from exhaustive type checking with a TypeScript never type in the default case

Performance Considerations 🚀

Excellent performance optimizations:

  • Binary search insertion: O(log n) complexity for maintaining sorted order
  • Map-based lookups: O(1) for ID-based operations
  • Efficient re-sorting only when necessary

Potential improvements:

  1. Consider implementing batch operations for multiple events arriving in quick succession
  2. The findIndex call in updateItem (line 196) could be optimized by maintaining an index map

Potential Bugs or Issues 🐛

  1. Edge case in addItem method (lines 147-150): When an item already exists, it calls updateItem but returns { added: false, removed: false } without the modified flag. This might confuse consumers who expect modified: true when an existing item is updated.

  2. Race condition potential: If multiple watch events arrive simultaneously, the current implementation doesn't have any locking mechanism. While JavaScript is single-threaded, rapid events could lead to unexpected behavior.

  3. Memory management: The itemsById Map will hold references to all items. For long-running applications with high churn, consider implementing a cleanup mechanism.

Security Concerns 🔒

No significant security issues identified. The implementation:

  • Doesn't execute any user-provided code unsafely
  • Properly handles untrusted data from watch events
  • Doesn't expose internal state inappropriately

Test Coverage 🧪

Excellent test coverage including:

  • Comparator function with various data types
  • Sort order (ascending/descending)
  • Null/undefined handling
  • CRUD operations with sorting
  • Limit enforcement
  • Edge cases

Missing test scenarios:

  1. Concurrent event handling
  2. Performance tests with large datasets
  3. Custom getId function behavior
  4. Error scenarios (e.g., invalid event data)

Additional Suggestions

  1. Consider adding event debouncing: For UI updates, rapid changes might benefit from debouncing
  2. Add telemetry/metrics: Track performance metrics like insertion time and list size
  3. Configuration validation: Add runtime validation for options (e.g., ensure limit > 0)
  4. Consider immutability: Return frozen arrays from getItems() to prevent external mutations

Code-Specific Feedback

src/utils/watch-list-manager.ts:184-190: The updateItem method adds a non-existing item, which might be unexpected behavior. Consider either throwing an error or documenting this behavior more prominently.

src/utils/watch-list-manager.ts:38-40: Good null handling, but consider making the "push to end" behavior configurable, as some use cases might prefer pushing nulls to the beginning.

Summary

This is a solid implementation that will significantly improve the performance of client-side sorted lists from watch subscriptions. The code is production-ready with minor improvements suggested above. Great work on the comprehensive documentation and test coverage! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Live Query Live query subscription feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add client-side sorting optimization for live query subscriptions

2 participants