mirror of
https://github.com/tiennm99/coolify.git
synced 2026-04-17 17:21:04 +00:00
docs: update application architecture and database patterns for request-level caching best practices
This commit is contained in:
@@ -283,14 +283,22 @@ class EnvironmentVariable extends Model
|
|||||||
|
|
||||||
### **Team-Based Soft Scoping**
|
### **Team-Based Soft Scoping**
|
||||||
|
|
||||||
All major resources include team-based query scoping:
|
All major resources include team-based query scoping with request-level caching:
|
||||||
|
|
||||||
```php
|
```php
|
||||||
// Automatic team filtering
|
// ✅ CORRECT - Use cached methods (request-level cache via once())
|
||||||
$applications = Application::ownedByCurrentTeam()->get();
|
$applications = Application::ownedByCurrentTeamCached();
|
||||||
$servers = Server::ownedByCurrentTeam()->get();
|
$servers = Server::ownedByCurrentTeamCached();
|
||||||
|
|
||||||
|
// ✅ CORRECT - Filter cached collection in memory
|
||||||
|
$activeServers = Server::ownedByCurrentTeamCached()->where('is_active', true);
|
||||||
|
|
||||||
|
// Only use query builder when you need eager loading or fresh data
|
||||||
|
$projects = Project::ownedByCurrentTeam()->with('environments')->get();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See [Database Patterns](.ai/patterns/database-patterns.md#request-level-caching-with-ownedbycurrentteamcached) for full documentation.
|
||||||
|
|
||||||
### **Configuration Inheritance**
|
### **Configuration Inheritance**
|
||||||
|
|
||||||
Environment variables cascade from:
|
Environment variables cascade from:
|
||||||
|
|||||||
@@ -243,6 +243,59 @@ Server::chunk(100, function ($servers) {
|
|||||||
- **Composite indexes** for common queries
|
- **Composite indexes** for common queries
|
||||||
- **Unique constraints** for business rules
|
- **Unique constraints** for business rules
|
||||||
|
|
||||||
|
### Request-Level Caching with ownedByCurrentTeamCached()
|
||||||
|
|
||||||
|
Many models have both `ownedByCurrentTeam()` (returns query builder) and `ownedByCurrentTeamCached()` (returns cached collection). **Always prefer the cached version** to avoid duplicate database queries within the same request.
|
||||||
|
|
||||||
|
**Models with cached methods available:**
|
||||||
|
- `Server`, `PrivateKey`, `Project`
|
||||||
|
- `Application`
|
||||||
|
- `StandalonePostgresql`, `StandaloneMysql`, `StandaloneRedis`, `StandaloneMariadb`, `StandaloneMongodb`, `StandaloneKeydb`, `StandaloneDragonfly`, `StandaloneClickhouse`
|
||||||
|
- `Service`, `ServiceApplication`, `ServiceDatabase`
|
||||||
|
|
||||||
|
**Usage patterns:**
|
||||||
|
```php
|
||||||
|
// ✅ CORRECT - Uses request-level cache (via Laravel's once() helper)
|
||||||
|
$servers = Server::ownedByCurrentTeamCached();
|
||||||
|
|
||||||
|
// ❌ AVOID - Makes a new database query each time
|
||||||
|
$servers = Server::ownedByCurrentTeam()->get();
|
||||||
|
|
||||||
|
// ✅ CORRECT - Filter cached collection in memory
|
||||||
|
$activeServers = Server::ownedByCurrentTeamCached()->where('is_active', true);
|
||||||
|
$server = Server::ownedByCurrentTeamCached()->firstWhere('id', $serverId);
|
||||||
|
$serverIds = Server::ownedByCurrentTeamCached()->pluck('id');
|
||||||
|
|
||||||
|
// ❌ AVOID - Making filtered database queries when data is already cached
|
||||||
|
$activeServers = Server::ownedByCurrentTeam()->where('is_active', true)->get();
|
||||||
|
```
|
||||||
|
|
||||||
|
**When to use which:**
|
||||||
|
- `ownedByCurrentTeamCached()` - **Default choice** for reading team data
|
||||||
|
- `ownedByCurrentTeam()` - Only when you need to chain query builder methods that can't be done on collections (like `with()` for eager loading), or when you explicitly need a fresh database query
|
||||||
|
|
||||||
|
**Implementation pattern for new models:**
|
||||||
|
```php
|
||||||
|
/**
|
||||||
|
* Get query builder for resources owned by current team.
|
||||||
|
* If you need all resources without further query chaining, use ownedByCurrentTeamCached() instead.
|
||||||
|
*/
|
||||||
|
public static function ownedByCurrentTeam()
|
||||||
|
{
|
||||||
|
return self::whereTeamId(currentTeam()->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all resources owned by current team (cached for request duration).
|
||||||
|
*/
|
||||||
|
public static function ownedByCurrentTeamCached()
|
||||||
|
{
|
||||||
|
return once(function () {
|
||||||
|
return self::ownedByCurrentTeam()->get();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Data Consistency Patterns
|
## Data Consistency Patterns
|
||||||
|
|
||||||
### Database Transactions
|
### Database Transactions
|
||||||
|
|||||||
@@ -222,6 +222,7 @@ class MyComponent extends Component
|
|||||||
- Queue heavy operations
|
- Queue heavy operations
|
||||||
- Optimize database queries with proper indexes
|
- Optimize database queries with proper indexes
|
||||||
- Use chunking for large data operations
|
- Use chunking for large data operations
|
||||||
|
- **CRITICAL**: Use `ownedByCurrentTeamCached()` instead of `ownedByCurrentTeam()->get()`
|
||||||
|
|
||||||
### Code Style
|
### Code Style
|
||||||
- Follow PSR-12 coding standards
|
- Follow PSR-12 coding standards
|
||||||
@@ -317,4 +318,5 @@ This file contains high-level guidelines for Claude Code. For **more detailed, t
|
|||||||
|
|
||||||
|
|
||||||
Random other things you should remember:
|
Random other things you should remember:
|
||||||
- App\Models\Application::team must return a relationship instance., always use team()
|
- App\Models\Application::team must return a relationship instance., always use team()
|
||||||
|
- Always use `Model::ownedByCurrentTeamCached()` instead of `Model::ownedByCurrentTeam()->get()` for team-scoped queries to avoid duplicate database queries
|
||||||
Reference in New Issue
Block a user