Put Federation on async executor
This commit is contained in:
parent
fde80672f2
commit
0e32aab244
2 changed files with 31 additions and 5 deletions
|
|
@ -201,13 +201,27 @@ public class CommentController {
|
|||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
||||
}
|
||||
|
||||
// Soft delete
|
||||
// Soft delete locally
|
||||
comment.setDeleted(true);
|
||||
commentRepository.save(comment);
|
||||
|
||||
log.info("User {} deleted comment {}", user.getUsername(), commentId);
|
||||
|
||||
// TODO: Send ActivityPub Delete activity to followers if activity is public
|
||||
// Federate the deletion to remote followers so they tombstone their cached
|
||||
// copy of the Note. The visibility check mirrors createComment(): the
|
||||
// original Create was only sent if the parent activity was PUBLIC or
|
||||
// FOLLOWERS, so the Delete needs to follow the same audience rule. The
|
||||
// commentUri must match exactly what was used in the original Create
|
||||
// activity, otherwise remote servers won't be able to match the tombstone
|
||||
// to the cached note.
|
||||
Activity activity = activityRepository.findById(activityId).orElse(null);
|
||||
if (activity != null
|
||||
&& (activity.getVisibility() == Activity.Visibility.PUBLIC
|
||||
|| activity.getVisibility() == Activity.Visibility.FOLLOWERS)) {
|
||||
String commentUri = baseUrl + "/activities/" + activityId + "/comments/" + commentId;
|
||||
federationService.sendDeleteActivity(commentUri, user);
|
||||
log.info("Sent Delete federation for comment {} on activity {}", commentId, activityId);
|
||||
}
|
||||
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -311,10 +311,16 @@ public class FederationService {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all follower inbox URLs for a local user.
|
||||
* Get the inbox URLs of all <em>remote</em> followers of a local user.
|
||||
*
|
||||
* <p>Local followers are deliberately skipped: they live on the same server and
|
||||
* see new activities via the local timeline queries, so there is nothing to
|
||||
* federate to them. Without this filter, every call would attempt to
|
||||
* {@code fetchRemoteActor(null)} for each local follower row, log a stack trace
|
||||
* at ERROR level, and then drop the resulting null from the inbox list.
|
||||
*
|
||||
* @param userId the local user's ID
|
||||
* @return list of inbox URLs
|
||||
* @return list of remote follower inbox URLs (deduplicated, shared inbox preferred)
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public List<String> getFollowerInboxes(UUID userId) {
|
||||
|
|
@ -325,6 +331,7 @@ public class FederationService {
|
|||
List<Follow> followers = followRepository.findAcceptedFollowersByActorUri(actorUri);
|
||||
|
||||
return followers.stream()
|
||||
.filter(follow -> follow.getRemoteActorUri() != null) // skip local followers (no federation needed)
|
||||
.map(follow -> {
|
||||
try {
|
||||
RemoteActor actor = remoteActorRepository.findByActorUri(follow.getRemoteActorUri())
|
||||
|
|
@ -529,9 +536,14 @@ public class FederationService {
|
|||
/**
|
||||
* Send a Delete activity to notify followers that an object has been deleted.
|
||||
*
|
||||
* @param objectUri the URI of the deleted object (e.g., activity URI)
|
||||
* <p>Runs on the {@code taskExecutor} pool. Used for both activity deletes and
|
||||
* comment (Note) deletes — the user-facing HTTP response shouldn't wait on the
|
||||
* federation fanout to remote follower inboxes.
|
||||
*
|
||||
* @param objectUri the URI of the deleted object (e.g., activity URI or comment Note URI)
|
||||
* @param sender the user who deleted the object
|
||||
*/
|
||||
@Async("taskExecutor")
|
||||
public void sendDeleteActivity(String objectUri, User sender) {
|
||||
try {
|
||||
String deleteId = baseUrl + "/activities/delete/" + UUID.randomUUID();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue