All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openmetadata.service.util.WebsocketNotificationHandler Maven / Gradle / Ivy

There is a newer version: 1.5.11
Show newest version
/*
 *  Copyright 2021 Collate
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *  http://www.apache.org/licenses/LICENSE-2.0
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.openmetadata.service.util;

import static org.openmetadata.service.Entity.TEAM;
import static org.openmetadata.service.Entity.USER;

import java.time.Instant;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.core.Response;
import lombok.extern.slf4j.Slf4j;
import org.openmetadata.schema.entity.feed.Thread;
import org.openmetadata.schema.entity.teams.Team;
import org.openmetadata.schema.entity.teams.User;
import org.openmetadata.schema.type.AnnouncementDetails;
import org.openmetadata.schema.type.EntityReference;
import org.openmetadata.schema.type.Post;
import org.openmetadata.schema.type.Relationship;
import org.openmetadata.service.Entity;
import org.openmetadata.service.jdbi3.CollectionDAO;
import org.openmetadata.service.resources.feeds.MessageParser;
import org.openmetadata.service.socket.WebSocketManager;

@Slf4j
public class WebsocketNotificationHandler {
  private final ExecutorService threadScheduler;

  public WebsocketNotificationHandler() {
    this.threadScheduler = Executors.newFixedThreadPool(1);
  }

  public void processNotifications(ContainerResponseContext responseContext) {
    threadScheduler.submit(
        () -> {
          try {
            handleNotifications(responseContext);
          } catch (Exception ex) {
            LOG.error("[NotificationHandler] Failed to use mapper in converting to Json", ex);
          }
        });
  }

  private void handleNotifications(ContainerResponseContext responseContext) {
    int responseCode = responseContext.getStatus();
    if (responseCode == Response.Status.CREATED.getStatusCode()
        && responseContext.getEntity() != null
        && responseContext.getEntity().getClass().equals(Thread.class)) {
      Thread thread = (Thread) responseContext.getEntity();
      switch (thread.getType()) {
        case Task -> handleTaskNotification(thread);
        case Conversation -> handleConversationNotification(thread);
        case Announcement -> handleAnnouncementNotification(thread);
      }
    }
  }

  public static void handleTaskNotification(Thread thread) {
    String jsonThread = JsonUtils.pojoToJson(thread);
    if (thread.getPostsCount() == 0) {
      List assignees = thread.getTask().getAssignees();
      Set receiversList = new HashSet<>();
      // Update Assignee
      assignees.forEach(
          e -> {
            if (Entity.USER.equals(e.getType())) {
              receiversList.add(e.getId());
            } else if (Entity.TEAM.equals(e.getType())) {
              // fetch all that are there in the team
              List records =
                  Entity.getCollectionDAO()
                      .relationshipDAO()
                      .findTo(e.getId(), TEAM, Relationship.HAS.ordinal(), Entity.USER);
              records.forEach(eRecord -> receiversList.add(eRecord.getId()));
            }
          });

      // Send WebSocket Notification
      WebSocketManager.getInstance()
          .sendToManyWithUUID(receiversList, WebSocketManager.TASK_BROADCAST_CHANNEL, jsonThread);
    } else {
      List mentions;
      Post latestPost = thread.getPosts().get(thread.getPostsCount() - 1);
      mentions = MessageParser.getEntityLinks(latestPost.getMessage());
      notifyMentionedUsers(mentions, jsonThread);
    }
  }

  private void handleAnnouncementNotification(Thread thread) {
    String jsonThread = JsonUtils.pojoToJson(thread);
    AnnouncementDetails announcementDetails = thread.getAnnouncement();
    Long currentTimestamp = Instant.now().getEpochSecond();
    if (announcementDetails.getStartTime() <= currentTimestamp
        && currentTimestamp <= announcementDetails.getEndTime()) {
      WebSocketManager.getInstance()
          .broadCastMessageToAll(WebSocketManager.ANNOUNCEMENT_CHANNEL, jsonThread);
    }
  }

  private void handleConversationNotification(Thread thread) {
    String jsonThread = JsonUtils.pojoToJson(thread);
    WebSocketManager.getInstance()
        .broadCastMessageToAll(WebSocketManager.FEED_BROADCAST_CHANNEL, jsonThread);
    List mentions;
    if (thread.getPostsCount() == 0) {
      mentions = MessageParser.getEntityLinks(thread.getMessage());
    } else {
      Post latestPost = thread.getPosts().get(thread.getPostsCount() - 1);
      mentions = MessageParser.getEntityLinks(latestPost.getMessage());
    }
    notifyMentionedUsers(mentions, jsonThread);
  }

  private static void notifyMentionedUsers(
      List mentions, String jsonThread) {
    mentions.forEach(
        entityLink -> {
          String fqn = entityLink.getEntityFQN();
          if (USER.equals(entityLink.getEntityType())) {
            User user = Entity.getCollectionDAO().userDAO().findEntityByName(fqn);
            WebSocketManager.getInstance()
                .sendToOne(user.getId(), WebSocketManager.MENTION_CHANNEL, jsonThread);
          } else if (TEAM.equals(entityLink.getEntityType())) {
            Team team = Entity.getCollectionDAO().teamDAO().findEntityByName(fqn);
            // fetch all that are there in the team
            List records =
                Entity.getCollectionDAO()
                    .relationshipDAO()
                    .findTo(team.getId(), TEAM, Relationship.HAS.ordinal(), USER);
            // Notify on WebSocket for Realtime
            WebSocketManager.getInstance()
                .sendToManyWithString(records, WebSocketManager.MENTION_CHANNEL, jsonThread);
          }
        });
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy