Interface TaskStore
- All Known Implementing Classes:
InMemoryTaskStore,JpaDatabaseTaskStore
TaskStore is responsible for persisting task state including status updates, artifacts,
message history, and metadata. It's called by DefaultRequestHandler
and TaskManager to save task state as agents process requests and generate events.
Persistence Guarantees
Tasks are persisted:- After each status update event (SUBMITTED, WORKING, COMPLETED, etc.)
- After each artifact is added
- Before events are distributed to clients (ensures consistency)
- Before push notifications are sent
Default Implementation
InMemoryTaskStore:
- Stores tasks in
ConcurrentHashMap - Also implements
TaskStateProviderfor queue lifecycle decisions - Thread-safe for concurrent operations
- Tasks lost on application restart
Alternative Implementations
- extras/task-store-database-jpa:
JpaDatabaseTaskStorewith PostgreSQL/MySQL persistence
- Survive application restarts
- Enable task sharing across server instances
- Typically also implement
TaskStateProviderfor integrated state queries - Support transaction boundaries for consistency
Relationship to TaskStateProvider
Many TaskStore implementations also implementTaskStateProvider to provide
queue lifecycle management with task state information:
@ApplicationScoped
public class InMemoryTaskStore implements TaskStore, TaskStateProvider {
// Provides both persistence and state queries
public boolean isTaskFinalized(String taskId) {
Task task = tasks.get(taskId);
return task != null && task.status().state().isFinal();
}
}
CDI Extension Pattern
@ApplicationScoped
@Alternative
@Priority(50) // Higher than default InMemoryTaskStore
public class JpaDatabaseTaskStore implements TaskStore, TaskStateProvider {
@PersistenceContext
EntityManager em;
@Transactional
public void save(Task task) {
TaskEntity entity = toEntity(task);
em.merge(entity);
}
}
Thread Safety
Implementations must be thread-safe. Multiple threads will call methods concurrently for different tasks. Concurrentsave() calls for the same task must handle
conflicts appropriately (last-write-wins, optimistic locking, etc.).
List Operation Performance
Thelist(ListTasksParams, ServerCallContext) method may need to scan and filter
many tasks. Database implementations should:
- Use indexes on contextId, status, lastUpdatedAt
- Implement efficient pagination with stable ordering
- Consider caching for frequently-accessed task lists
Exception Contract
All TaskStore methods may throwTaskStoreException or its subclasses to indicate
persistence failures:
TaskSerializationException- JSON/data format errorsTaskPersistenceException- Database/storage system failures
When to Throw TaskSerializationException
Use when task data cannot be serialized or deserialized:- JSON parsing errors during
get()operations - JSON serialization errors during
save()operations - Invalid enum values or missing required fields
- Schema version mismatches after upgrades
When to Throw TaskPersistenceException
Use when the storage system fails:- Database connection timeouts
- Transaction deadlocks
- Connection pool exhausted
- Disk full / quota exceeded
- Database constraint violations
- Insufficient permissions
Implementer Example
@Override
public void save(Task task, boolean isReplicated) {
try {
String json = objectMapper.writeValueAsString(task);
} catch (JsonProcessingException e) {
throw new TaskSerializationException(task.id(), "Failed to serialize task", e);
}
try {
entityManager.merge(toEntity(json));
} catch (PersistenceException e) {
throw new TaskPersistenceException(task.id(), "Database save failed", e);
}
}
Exception Handling
MainEventBusProcessor catches TaskStore exceptions and
wraps them in InternalError events for client distribution.-
Method Summary
Modifier and TypeMethodDescriptionvoidDeletes a task by its ID.@Nullable TaskRetrieves a task by its ID.list(ListTasksParams params, @Nullable ServerCallContext context) List tasks with optional filtering and pagination.voidSaves or updates a task.
-
Method Details
-
save
Saves or updates a task.- Parameters:
task- the task to saveisReplicated- true if this task update came from a replicated event, false if it originated locally. Used to prevent feedback loops in replicated scenarios (e.g., don't fire TaskFinalizedEvent for replicated updates)- Throws:
TaskSerializationException- if the task cannot be serialized to storage format (JSON parsing error, invalid field values, schema mismatch)TaskPersistenceException- if the storage system fails (database timeout, connection error, disk full)TaskStoreException- for other persistence failures not covered by specific subclasses
-
get
Retrieves a task by its ID.- Parameters:
taskId- the task identifier- Returns:
- the task if found, null otherwise
- Throws:
TaskSerializationException- if the persisted task data cannot be deserialized (corrupted JSON, schema incompatibility)TaskPersistenceException- if the storage system fails during retrieval (database connection error, query timeout)TaskStoreException- for other retrieval failures not covered by specific subclasses
-
delete
Deletes a task by its ID.- Parameters:
taskId- the task identifier- Throws:
TaskPersistenceException- if the storage system fails during deletion (database connection error, transaction timeout, constraint violation)TaskStoreException- for other deletion failures not covered by specific subclasses
-
list
List tasks with optional filtering and pagination.Authorization filtering: When a
TaskAuthorizationProviderbean is present, implementations must callcheckReadfor each candidate task and exclude tasks for which the check returnsfalse. The filtering should be applied before pagination so that page sizes are correct from the caller's perspective. If no provider is present, all tasks are returned.⚠ Custom implementation warning: Returning unfiltered results bypasses the authorization model and can leak tasks belonging to other users. Custom implementations must apply per-task
checkReadfiltering before pagination. TheTaskAuthorizationProvidershould be declared as a CDI dependency and injected via the constructor or@Inject.- Parameters:
params- the filtering and pagination parameterscontext- the server call context (used for authorization filtering)- Returns:
- the list of tasks matching the criteria with pagination info
- Throws:
TaskSerializationException- if any persisted task data cannot be deserialized during listing (corrupted JSON in database)TaskPersistenceException- if the storage system fails during the list operation (database query timeout, connection error)TaskStoreException- for other listing failures not covered by specific subclasses
-