- Build solution:
dotnet build - Run unit tests only:
dotnet test --filter "TestCategory!=Integration" - Run all tests (including integration):
dotnet test - Run integration tests only:
dotnet test --filter "TestCategory=Integration" - Run specific test project:
dotnet test tests/HappyNotes.Services.Tests - Run single test class:
dotnet test --filter "FullyQualifiedName~NoteServiceTests" - Run single test method:
dotnet test --filter "FullyQualifiedName~NoteServiceTests.Get_WithExistingPublicNote_ReturnsNote"
CORRECT: dotnet test tests/ProjectName or dotnet test --filter "Pattern"
WRONG: dotnet test tests/ProjectName/SpecificFile.cs (❌ Cannot test individual .cs files)
Common Patterns:
- Single test:
dotnet test --filter "FullyQualifiedName~TestMethodName" - Test class:
dotnet test --filter "FullyQualifiedName~TestClassName" - Multiple runs: Use
forloops with project-level commands, not file-level
- Redis integration tests require a Redis instance for sync queue functionality
- Set
REDIS_CONNECTION_STRINGenvironment variable (defaults tolocalhost:6379) - Tests are automatically skipped if Redis is unavailable
- Local Docker:
docker run --rm -p 6379:6379 redis:7-alpine - Queue Tests: AtomicDequeueTests, DelayedTaskProcessingTests, RedisSyncQueueServiceTests
- Handler Tests: TelegramSyncHandlerTests, MastodonSyncHandlerTests (when implemented)
- Unit tests: Run on every push/PR (fast feedback)
- Integration tests: Run with Redis service container
- Parallel execution: Unit and integration tests run simultaneously
- PR checks: Quick unit test feedback for all PRs
- Label-triggered: Add
needs-integration-testslabel to run integration tests on PRs
- Naming: PascalCase for classes/methods, camelCase for variables/parameters
- Types: Use explicit types; enable nullable reference types
- Regex: Use GeneratedRegex attributes with partial methods for better performance
- Error Handling: Use CustomException with EventId for domain errors; ArgumentException for invalid inputs
- Testing: Use NUnit with Moq framework; follow AAA pattern (Arrange-Act-Assert)
- Architecture: Follow repository pattern with services for business logic
- Dependencies: Use constructor injection with interfaces for testability
- Api.Framework: Base classes and utilities
- HappyNotes.Common: Shared constants and extensions
- HappyNotes.Services: Business logic implementation
- SyncQueue: Redis-based queue system for reliable sync operations
- HappyNotes.Entities: Database model classes
- HappyNotes.Repositories: Data access layer
- HappyNotes.Dto: Data transfer objects
- HappyNotes.Models: Request/response models
The application uses a Redis-based queue system for reliable background sync operations to external services (Telegram, Mastodon). This ensures resilience, retry capabilities, and horizontal scalability.
- SyncQueueService: Redis queue management (enqueue, dequeue, retry)
- SyncQueueProcessor: Background service that processes queued tasks
- Sync Handlers: Service-specific handlers (TelegramSyncHandler, MastodonSyncHandler)
- Multi-layer Retry Strategy: 3-tier retry system with exponential backoff
- ✅ Telegram: Full queue integration with channel management
- ✅ Mastodon: Complete queue integration with instance management
- ⏳ ManticoreSearch: Not yet migrated (still uses direct sync)
- Redis Connection: Set
REDIS_CONNECTION_STRINGenvironment variable - Queue Options: Configure retry attempts, delays, and timeouts in appsettings.json
- Handler Registration: All handlers auto-registered via DI container
- Exponential Backoff: 1min → 2min → 4min → 8min retry delays
- Task Recovery: Automatic recovery of expired/failed tasks
- Service Isolation: Per-service queues prevent cross-contamination
- Graceful Degradation: Queue failures don't crash the main application
When analyzing large codebases or multiple files that might exceed context limits, use the Gemini CLI with its massive
context window. Use gemini -p to leverage Google Gemini's large context capacity.
Use the @ syntax to include files and directories in your Gemini prompts. The paths should be relative to WHERE you run the
gemini command:
Single file analysis: gemini -p "@src/main.py Explain this file's purpose and structure"
Multiple files: gemini -p "@package.json @src/index.js Analyze the dependencies used in the code"
Entire directory: gemini -p "@src/ Summarize the architecture of this codebase"
Multiple directories: gemini -p "@src/ @tests/ Analyze test coverage for the source code"
Current directory and subdirectories: gemini -p "@./ Give me an overview of this entire project"
gemini --all_files -p "Analyze the project structure and dependencies"
Implementation Verification Examples
Check if a feature is implemented: gemini -p "@src/ @lib/ Has dark mode been implemented in this codebase? Show me the relevant files and functions"
Verify authentication implementation: gemini -p "@src/ @middleware/ Is JWT authentication implemented? List all auth-related endpoints and middleware"
Check for specific patterns: gemini -p "@src/ Are there any React hooks that handle WebSocket connections? List them with file paths"
Verify error handling: gemini -p "@src/ @api/ Is proper error handling implemented for all API endpoints? Show examples of try-catch blocks"
Check for rate limiting: gemini -p "@backend/ @middleware/ Is rate limiting implemented for the API? Show the implementation details"
Verify caching strategy: gemini -p "@src/ @lib/ @services/ Is Redis caching implemented? List all cache-related functions and their usage"
Check for specific security measures: gemini -p "@src/ @api/ Are SQL injection protections implemented? Show how user inputs are sanitized"
Verify test coverage for features: gemini -p "@src/payment/ @tests/ Is the payment processing module fully tested? List all test cases"
When to Use Gemini CLI
Use gemini -p when:
- Analyzing entire codebases or large directories
- Comparing multiple large files
- Need to understand project-wide patterns or architecture
- Current context window is insufficient for the task
- Working with files totaling more than 100KB
- Verifying if specific features, patterns, or security measures are implemented
- Checking for the presence of certain coding patterns across the entire codebase
Important Notes
- Paths in @ syntax are relative to your current working directory when invoking gemini
- The CLI will include file contents directly in the context
- No need for --yolo flag for read-only analysis
- Gemini's context window can handle entire codebases that would overflow Claude's context
- When checking implementations, be specific about what you're looking for to get accurate results