feat(alerts): core repo — filter params + markRead/softDelete/bulkAck/restore; drop AlertReadRepository
- listForInbox gains tri-state acked/read filter params - countUnreadBySeverityForUser(envId, userId) → countUnreadBySeverity(envId, userId, groupIds, roleNames) - new methods: markRead, bulkMarkRead, softDelete, bulkSoftDelete, bulkAck, restore - delete AlertReadRepository — read is now global on alert_instances.read_at Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,26 +7,27 @@ import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface AlertInstanceRepository {
|
||||
AlertInstance save(AlertInstance instance); // upsert by id
|
||||
AlertInstance save(AlertInstance instance);
|
||||
Optional<AlertInstance> findById(UUID id);
|
||||
Optional<AlertInstance> findOpenForRule(UUID ruleId); // state IN ('PENDING','FIRING','ACKNOWLEDGED')
|
||||
|
||||
/**
|
||||
* Unfiltered inbox listing. Convenience overload that delegates to the filtered
|
||||
* variant with {@code states}/{@code severities} set to {@code null} (no filter).
|
||||
*/
|
||||
/** Open instance for a rule: state IN ('PENDING','FIRING') AND deleted_at IS NULL. */
|
||||
Optional<AlertInstance> findOpenForRule(UUID ruleId);
|
||||
|
||||
/** Unfiltered inbox listing — convenience overload. */
|
||||
default List<AlertInstance> listForInbox(UUID environmentId,
|
||||
List<String> userGroupIdFilter,
|
||||
String userId,
|
||||
List<String> userRoleNames,
|
||||
int limit) {
|
||||
return listForInbox(environmentId, userGroupIdFilter, userId, userRoleNames, null, null, limit);
|
||||
return listForInbox(environmentId, userGroupIdFilter, userId, userRoleNames,
|
||||
null, null, null, null, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inbox listing with optional state + severity filters. {@code null} or empty lists mean
|
||||
* "no filter on that field". When both lists are non-empty the row must match at least one
|
||||
* value from each list (AND between dimensions, OR within).
|
||||
* Inbox listing with optional filters. {@code null} or empty lists mean no filter.
|
||||
* {@code acked} and {@code read} are tri-state: {@code null} = no filter,
|
||||
* {@code TRUE} = only acked/read, {@code FALSE} = only unacked/unread.
|
||||
* Always excludes soft-deleted rows ({@code deleted_at IS NOT NULL}).
|
||||
*/
|
||||
List<AlertInstance> listForInbox(UUID environmentId,
|
||||
List<String> userGroupIdFilter,
|
||||
@@ -34,20 +35,40 @@ public interface AlertInstanceRepository {
|
||||
List<String> userRoleNames,
|
||||
List<AlertState> states,
|
||||
List<AlertSeverity> severities,
|
||||
Boolean acked,
|
||||
Boolean read,
|
||||
int limit);
|
||||
|
||||
/**
|
||||
* Count unread alert instances for the user, grouped by severity.
|
||||
* <p>
|
||||
* Always returns a map with an entry for every {@link AlertSeverity} (value 0 if no rows),
|
||||
* so callers never need null-checks. Total unread count is the sum of the values.
|
||||
* Count unread alert instances visible to the user, grouped by severity.
|
||||
* Visibility: targets user directly, or via one of the given groups/roles.
|
||||
* "Unread" = {@code read_at IS NULL AND deleted_at IS NULL}.
|
||||
*/
|
||||
Map<AlertSeverity, Long> countUnreadBySeverityForUser(UUID environmentId, String userId);
|
||||
Map<AlertSeverity, Long> countUnreadBySeverity(UUID environmentId,
|
||||
String userId,
|
||||
List<String> groupIds,
|
||||
List<String> roleNames);
|
||||
|
||||
void ack(UUID id, String userId, Instant when);
|
||||
void resolve(UUID id, Instant when);
|
||||
void markSilenced(UUID id, boolean silenced);
|
||||
void deleteResolvedBefore(Instant cutoff);
|
||||
|
||||
/** FIRING instances whose reNotify cadence has elapsed since last notification. */
|
||||
/** Set {@code read_at = when} if currently null. Idempotent. */
|
||||
void markRead(UUID id, Instant when);
|
||||
/** Bulk variant — single UPDATE. */
|
||||
void bulkMarkRead(List<UUID> ids, Instant when);
|
||||
|
||||
/** Set {@code deleted_at = when} if currently null. Idempotent. */
|
||||
void softDelete(UUID id, Instant when);
|
||||
/** Bulk variant — single UPDATE. */
|
||||
void bulkSoftDelete(List<UUID> ids, Instant when);
|
||||
|
||||
/** Clear {@code deleted_at}. Undo for soft-delete. Idempotent. */
|
||||
void restore(UUID id);
|
||||
|
||||
/** Bulk ack — single UPDATE. Each row gets {@code acked_at=when, acked_by=userId} if unacked. */
|
||||
void bulkAck(List<UUID> ids, String userId, Instant when);
|
||||
|
||||
List<AlertInstance> listFiringDueForReNotify(Instant now);
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
package com.cameleer.server.core.alerting;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public interface AlertReadRepository {
|
||||
void markRead(String userId, UUID alertInstanceId);
|
||||
void bulkMarkRead(String userId, List<UUID> alertInstanceIds);
|
||||
}
|
||||
Reference in New Issue
Block a user