ワンクリックで
cqrs
Command Query Responsibility Segregation patterns for separating write and read models.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Command Query Responsibility Segregation patterns for separating write and read models.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Optimize token usage and context window discipline. Reduce costs and improve response quality through smart context management.
Unified context lifecycle for FlowDeck sessions — ingest, filter, prune, protect, summarize, and persist with telemetry.
Predict affected files, modules, APIs, tests, and DB paths before changes. Returns an impact map for human review.
Map architecture, conventions, and file structure into `.codebase/`. Use when onboarding or before deep feature work.
Plan differently when the agent has low certainty — ask for clarification or narrow scope instead of pretending full understanding.
Protect critical context from pruning during compaction. Preserve active plans, safety files, pending operations, and user intent anchors.
| name | cqrs |
| description | Command Query Responsibility Segregation patterns for separating write and read models. |
| origin | FlowDeck |
Activate when:
| Aspect | Command | Query |
|---|---|---|
| Purpose | Modify state | Read state |
| Returns | Void / ACK | Data |
| Side Effects | Yes | No |
| Complexity | Business logic | Data shaping |
Commands and queries should use different models with different schemas optimized for their specific use case.
PlaceOrder, UpdatePrice)interface Command {
id: string; // Correlation ID
type: string; // Command type
payload: unknown; // Command data
metadata: {
userId: string;
timestamp: string;
correlationId: string;
};
}
interface CommandHandler<T extends Command> {
execute(command: T): Promise<CommandResult>;
}
GetUserOrders, FindActiveProducts)interface Query {
id: string;
type: string;
parameters: Record<string, unknown>;
pagination?: { page: number; limit: number };
sorting?: { field: string; direction: 'asc' | 'desc' }[];
}
interface QueryHandler<T extends Query> {
execute(query: T): Promise<QueryResult>;
}
When commands and queries share data:
// Synchronous synchronization
async function placeOrder(command: PlaceOrderCommand): Promise<void> {
const order = Order.create(command.payload);
await this.transactionManager.execute(async (tx) => {
// Write to command model
await this.orderRepo.save(order, tx);
// Synchronize to read model
const readModel = {
orderId: order.id,
customerId: order.customerId,
status: order.status,
total: order.total,
placedAt: order.placedAt
};
await this.orderReadRepo.save(readModel, tx);
});
}
If read and write models are updated asynchronously:
// commands/place-order.command.ts
interface PlaceOrderCommand {
orderId?: string; // Optional, generated if not provided
customerId: string;
items: OrderItem[];
paymentMethod: 'CARD' | 'PAYPAL';
}
class PlaceOrderCommandHandler implements CommandHandler<PlaceOrderCommand> {
async execute(command: PlaceOrderCommand): Promise<CommandResult> {
// 1. Validate command
const validation = this.validate(command);
if (!validation.success) {
return CommandResult.failure(validation.errors);
}
// 2. Check business invariants
const customer = await this.customerRepo.findById(command.customerId);
if (!customer.isActive) {
return CommandResult.failure('Customer account is not active');
}
// 3. Create aggregate
const order = Order.create({
id: command.orderId,
customerId: command.customerId,
items: command.items
});
// 4. Persist
await this.orderRepo.save(order);
// 5. Emit event for async processing
await this.eventBus.publish(OrderPlacedEvent.fromOrder(order));
return CommandResult.success({ orderId: order.id });
}
}
// queries/get-order-details.query.ts
interface GetOrderDetailsQuery {
orderId: string;
includeItems?: boolean;
}
interface OrderDetailsReadModel {
orderId: string;
customerId: string;
customerName: string;
status: string;
total: number;
placedAt: string;
items?: OrderItemReadModel[];
}
class GetOrderDetailsQueryHandler implements QueryHandler<GetOrderDetailsQuery, OrderDetailsReadModel> {
async execute(query: GetOrderDetailsQuery): Promise<OrderDetailsReadModel> {
const order = await this.readModelRepo.findOrderWithDetails(query.orderId);
if (!order) {
throw new QueryNotFoundError('Order not found');
}
const result: OrderDetailsReadModel = {
orderId: order.orderId,
customerId: order.customerId,
customerName: order.customerName,
status: order.status,
total: order.total,
placedAt: order.placedAt
};
if (query.includeItems) {
result.items = await this.readModelRepo.findOrderItems(query.orderId);
}
return result;
}
}
class CqrsMediator {
private commandHandlers: Map<string, CommandHandler<any>>;
private queryHandlers: Map<string, QueryHandler<any>>;
async send<T>(message: Command | Query): Promise<CommandResult | QueryResult> {
const handler = message instanceof Command
? this.commandHandlers.get(message.type)
: this.queryHandlers.get(message.type);
if (!handler) {
throw new HandlerNotFoundError(message.type);
}
return handler.execute(message);
}
}
// Usage
const result = await mediator.send(new PlaceOrderCommand({ ... }));
const orderDetails = await mediator.send(new GetOrderDetailsQuery({ orderId: '123' }));