Updated unassign for alarms, on user removing to be transactional

This commit is contained in:
imbeacon 2023-08-03 10:40:50 +03:00
parent 25778ce451
commit ed5b528964
10 changed files with 47 additions and 73 deletions

View File

@ -157,24 +157,6 @@ public class CustomerController extends BaseController {
checkParameter(CUSTOMER_ID, strCustomerId); checkParameter(CUSTOMER_ID, strCustomerId);
CustomerId customerId = new CustomerId(toUUID(strCustomerId)); CustomerId customerId = new CustomerId(toUUID(strCustomerId));
Customer customer = checkCustomerId(customerId, Operation.DELETE); Customer customer = checkCustomerId(customerId, Operation.DELETE);
TenantId tenantId = getTenantId();
PageLink pl = new PageLink(100);
boolean hasNext = true;
List<ListenableFuture<Void>> futures = new ArrayList<>();
while (hasNext) {
PageData<User> customerUsers = userService.findCustomerUsers(tenantId, customerId, pl);
for (User user : customerUsers.getData()) {
ListenableFuture<Void> future = tbAlarmService.unassignUserAlarms(tenantId, user, System.currentTimeMillis());
futures.add(future);
}
hasNext = customerUsers.hasNext();
if (hasNext) {
pl = pl.nextPageLink();
}
}
ListenableFuture<List<Void>> allFutures = Futures.allAsList(futures);
Futures.getChecked(allFutures, ThingsboardException.class);
tbCustomerService.delete(customer, getCurrentUser()); tbCustomerService.delete(customer, getCurrentUser());
} }

View File

@ -15,9 +15,6 @@
*/ */
package org.thingsboard.server.service.entitiy.alarm; package org.thingsboard.server.service.entitiy.alarm;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -32,7 +29,6 @@ import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.alarm.AlarmCommentType; import org.thingsboard.server.common.data.alarm.AlarmCommentType;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest;
import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.alarm.AlarmQueryV2;
import org.thingsboard.server.common.data.alarm.AlarmUpdateRequest; import org.thingsboard.server.common.data.alarm.AlarmUpdateRequest;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
@ -40,8 +36,6 @@ import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.TimePageLink;
import org.thingsboard.server.service.entitiy.AbstractTbEntityService; import org.thingsboard.server.service.entitiy.AbstractTbEntityService;
import java.util.List; import java.util.List;
@ -216,47 +210,6 @@ public class DefaultTbAlarmService extends AbstractTbEntityService implements Tb
return alarmInfo; return alarmInfo;
} }
@Override
public ListenableFuture<Void> unassignUserAlarms(TenantId tenantId, User user, long unassignTs) {
AlarmQueryV2 alarmQuery = AlarmQueryV2.builder().assigneeId(user.getId()).pageLink(new TimePageLink(Integer.MAX_VALUE)).build();
ListenableFuture<PageData<AlarmInfo>> foundUserAlarmsFuture = alarmService.findAlarmsV2(tenantId, alarmQuery);
FutureCallback<PageData<AlarmInfo>> callback = new FutureCallback<>() {
public void onSuccess(PageData<AlarmInfo> alarmsData) {
for (AlarmInfo alarm : alarmsData.getData()) {
unassignUserAlarm(tenantId, user, unassignTs, alarm);
}
}
public void onFailure(Throwable t) {
log.error("Cannot get alarms for user {}", user.getId(), t);
}
};
Futures.addCallback(foundUserAlarmsFuture, callback, dbExecutor);
return Futures.transform(foundUserAlarmsFuture, alarms -> null, dbExecutor);
}
private void unassignUserAlarm(TenantId tenantId, User user, long unassignTs, AlarmInfo alarm) {
AlarmApiCallResult result = alarmSubscriptionService.unassignAlarm(tenantId, alarm.getId(), getOrDefault(unassignTs));
if (!result.isSuccessful()) {
return;
}
if (result.isModified()) {
AlarmComment alarmComment = AlarmComment.builder()
.alarmId(alarm.getId())
.type(AlarmCommentType.SYSTEM)
.comment(JacksonUtil.newObjectNode().put("text", String.format("Alarm was unassigned because user %s - was deleted",
(user.getFirstName() == null || user.getLastName() == null) ? user.getName() : user.getFirstName() + " " + user.getLastName()))
.put("userId", user.getId().toString())
.put("subtype", "ASSIGN"))
.build();
try {
alarmCommentService.saveAlarmComment(alarm, alarmComment, user);
} catch (ThingsboardException e) {
log.error("Failed to save alarm comment", e);
}
notificationEntityService.notifyCreateOrUpdateAlarm(result.getAlarm(), ActionType.ALARM_UNASSIGNED, user);
}
}
@Override @Override
public Boolean delete(Alarm alarm, User user) { public Boolean delete(Alarm alarm, User user) {

View File

@ -15,12 +15,10 @@
*/ */
package org.thingsboard.server.service.entitiy.alarm; package org.thingsboard.server.service.entitiy.alarm;
import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.exception.ThingsboardException; import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.id.UserId;
public interface TbAlarmService { public interface TbAlarmService {
@ -39,7 +37,5 @@ public interface TbAlarmService {
AlarmInfo unassign(Alarm alarm, long unassignTs, User user) throws ThingsboardException; AlarmInfo unassign(Alarm alarm, long unassignTs, User user) throws ThingsboardException;
ListenableFuture<Void> unassignUserAlarms(TenantId tenantId, User user, long unassignTs);
Boolean delete(Alarm alarm, User user); Boolean delete(Alarm alarm, User user);
} }

View File

@ -15,8 +15,6 @@
*/ */
package org.thingsboard.server.service.entitiy.user; package org.thingsboard.server.service.entitiy.user;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -84,8 +82,6 @@ public class DefaultUserService extends AbstractTbEntityService implements TbUse
UserId userId = tbUser.getId(); UserId userId = tbUser.getId();
try { try {
ListenableFuture<Void> future = tbAlarmService.unassignUserAlarms(tbUser.getTenantId(), tbUser, System.currentTimeMillis());
Futures.getChecked(future, ThingsboardException.class);
userService.deleteUser(tenantId, userId); userService.deleteUser(tenantId, userId);
notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, customerId, userId, tbUser, notificationEntityService.notifyCreateOrUpdateOrDelete(tenantId, customerId, userId, tbUser,
user, ActionType.DELETED, true, null, customerId.toString()); user, ActionType.DELETED, true, null, customerId.toString());

View File

@ -17,6 +17,7 @@ package org.thingsboard.server.dao.alarm;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest;
@ -118,6 +119,8 @@ public interface AlarmService extends EntityDaoService {
PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId, PageData<AlarmData> findAlarmDataByQueryForEntities(TenantId tenantId,
AlarmDataQuery query, Collection<EntityId> orderedEntityIds); AlarmDataQuery query, Collection<EntityId> orderedEntityIds);
void unassignUserAlarms(TenantId tenantId, UserId userId, long unassignTs);
void deleteEntityAlarmRelations(TenantId tenantId, EntityId entityId); void deleteEntityAlarmRelations(TenantId tenantId, EntityId entityId);
long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query); long countAlarmsByQuery(TenantId tenantId, CustomerId customerId, AlarmCountQuery query);

View File

@ -77,6 +77,8 @@ public interface AlarmDao extends Dao<Alarm> {
PageData<AlarmId> findAlarmsIdsByEndTsBeforeAndTenantId(Long time, TenantId tenantId, PageLink pageLink); PageData<AlarmId> findAlarmsIdsByEndTsBeforeAndTenantId(Long time, TenantId tenantId, PageLink pageLink);
List<Alarm> findAlarmByAssigneeId(UUID key);
void createEntityAlarmRecord(EntityAlarm entityAlarm); void createEntityAlarmRecord(EntityAlarm entityAlarm);
List<EntityAlarm> findEntityAlarmRecords(TenantId tenantId, AlarmId id); List<EntityAlarm> findEntityAlarmRecords(TenantId tenantId, AlarmId id);

View File

@ -25,9 +25,12 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.alarm.Alarm; import org.thingsboard.server.common.data.alarm.Alarm;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
import org.thingsboard.server.common.data.alarm.AlarmComment;
import org.thingsboard.server.common.data.alarm.AlarmCommentType;
import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest; import org.thingsboard.server.common.data.alarm.AlarmCreateOrUpdateActiveRequest;
import org.thingsboard.server.common.data.alarm.AlarmInfo; import org.thingsboard.server.common.data.alarm.AlarmInfo;
import org.thingsboard.server.common.data.alarm.AlarmModificationRequest; import org.thingsboard.server.common.data.alarm.AlarmModificationRequest;
@ -84,6 +87,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
private final TenantService tenantService; private final TenantService tenantService;
private final AlarmDao alarmDao; private final AlarmDao alarmDao;
private final AlarmCommentDao alarmCommentDao;
private final EntityService entityService; private final EntityService entityService;
private final DataValidator<Alarm> alarmDataValidator; private final DataValidator<Alarm> alarmDataValidator;
@ -308,6 +312,28 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
return withPropagated(alarmDao.unassignAlarm(tenantId, alarmId, unassignTime)); return withPropagated(alarmDao.unassignAlarm(tenantId, alarmId, unassignTime));
} }
@Override
public void unassignUserAlarms(TenantId tenantId, UserId userId, long unassignTs) {
List<Alarm> alarms = findAlarmsByAssigneeId(userId);
for (Alarm alarm : alarms) {
AlarmApiCallResult result = unassignAlarm(alarm.getTenantId(), alarm.getId(), unassignTs);
if (!result.isSuccessful()) {
continue;
}
if (result.isModified()) {
AlarmComment alarmComment = AlarmComment.builder()
.alarmId(alarm.getId())
.type(AlarmCommentType.SYSTEM)
.comment(JacksonUtil.newObjectNode()
.put("text", "Alarm was unassigned because assigned user was deleted!")
.put("userId", userId.toString())
.put("subtype", "ASSIGN"))
.build();
alarmCommentDao.save(tenantId, alarmComment);
}
}
}
@Override @Override
public Alarm findAlarmById(TenantId tenantId, AlarmId alarmId) { public Alarm findAlarmById(TenantId tenantId, AlarmId alarmId) {
log.trace("Executing findAlarmById [{}]", alarmId); log.trace("Executing findAlarmById [{}]", alarmId);
@ -488,4 +514,10 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
} }
} }
private List<Alarm> findAlarmsByAssigneeId(UserId userId) {
log.trace("Executing findAlarmsByAssigneeId [{}]", userId);
validateId(userId, "Incorrect alarmId " + userId);
return alarmDao.findAlarmByAssigneeId(userId.getId());
}
} }

View File

@ -315,6 +315,9 @@ public interface AlarmRepository extends JpaRepository<AlarmEntity, UUID> {
@Query(value = "SELECT a FROM AlarmInfoEntity a WHERE a.tenantId = :tenantId AND a.id = :alarmId") @Query(value = "SELECT a FROM AlarmInfoEntity a WHERE a.tenantId = :tenantId AND a.id = :alarmId")
AlarmInfoEntity findAlarmInfoById(@Param("tenantId") UUID tenantId, @Param("alarmId") UUID alarmId); AlarmInfoEntity findAlarmInfoById(@Param("tenantId") UUID tenantId, @Param("alarmId") UUID alarmId);
@Query("SELECT a FROM AlarmEntity a WHERE a.assigneeId = :assigneeId")
List<AlarmEntity> findAlarmByAssigneeId(@Param("assigneeId") UUID assigneeId);
@Query(value = "SELECT create_or_update_active_alarm(:t_id, :c_id, :a_id, :a_created_ts, :a_o_id, :a_o_type, :a_type, :a_severity, " + @Query(value = "SELECT create_or_update_active_alarm(:t_id, :c_id, :a_id, :a_created_ts, :a_o_id, :a_o_type, :a_type, :a_severity, " +
":a_start_ts, :a_end_ts, :a_details, :a_propagate, :a_propagate_to_owner, " + ":a_start_ts, :a_end_ts, :a_details, :a_propagate, :a_propagate_to_owner, " +
":a_propagate_to_tenant, :a_propagation_types, :a_creation_enabled)", nativeQuery = true) ":a_propagate_to_tenant, :a_propagation_types, :a_creation_enabled)", nativeQuery = true)

View File

@ -285,6 +285,12 @@ public class JpaAlarmDao extends JpaAbstractDao<AlarmEntity, Alarm> implements A
.mapData(AlarmId::new); .mapData(AlarmId::new);
} }
@Override
public List<Alarm> findAlarmByAssigneeId(UUID key) {
List<AlarmEntity> assignedAlarms = alarmRepository.findAlarmByAssigneeId(key);
return DaoUtil.convertDataList(assignedAlarms);
}
@Override @Override
public void createEntityAlarmRecord(EntityAlarm entityAlarm) { public void createEntityAlarmRecord(EntityAlarm entityAlarm) {
log.debug("Saving entity {}", entityAlarm); log.debug("Saving entity {}", entityAlarm);

View File

@ -230,6 +230,7 @@ public class UserServiceImpl extends AbstractEntityService implements UserServic
public void deleteUser(TenantId tenantId, UserId userId) { public void deleteUser(TenantId tenantId, UserId userId) {
log.trace("Executing deleteUser [{}]", userId); log.trace("Executing deleteUser [{}]", userId);
validateId(userId, INCORRECT_USER_ID + userId); validateId(userId, INCORRECT_USER_ID + userId);
alarmService.unassignUserAlarms(tenantId, userId, System.currentTimeMillis());
UserCredentials userCredentials = userCredentialsDao.findByUserId(tenantId, userId.getId()); UserCredentials userCredentials = userCredentialsDao.findByUserId(tenantId, userId.getId());
userCredentialsDao.removeById(tenantId, userCredentials.getUuidId()); userCredentialsDao.removeById(tenantId, userCredentials.getUuidId());
userAuthSettingsDao.removeByUserId(userId); userAuthSettingsDao.removeByUserId(userId);