Untitled
unknown
plain_text
a year ago
4.5 kB
6
Indexable
package ru.crystals.sco3.business.process.dialogs;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import ru.crystals.sco3.business.entity.menu.RequestInformationFromUser;
import ru.crystals.sco3.business.entity.menu.UserInformationInputCompleted;
import ru.crystals.sco3.business.entity.menu.UserInformationType;
import ru.crystals.sco3.interfaces.process.api.ProcessAPI;
import ru.crystals.sco3.utilities.interfaces.service_executor.ServiceExecutor;
import javax.annotation.PostConstruct;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
@Slf4j
@Service
@RequiredArgsConstructor
public class DialogManager {
// нужен чтобы не допустить параллельного выполнения операций processAPI.runProcess(dialogProcess) и processAPI.endProcess(dialogProcess)
private final Object lock = new Object();
private final ServiceExecutor executor;
private final ProcessAPI processAPI;
private final Deque<DialogDescription> dialogs = new LinkedList<>();
private final AtomicLong dialogId = new AtomicLong();
private DialogProcess dialogProcess;
private DialogDescription currentDialog;
@PostConstruct
private void postConstruct() {
executor.execute(this::showDialogLoop, log, "ShowDialogLoop_Thread");
}
private void showDialogLoop() {
try {
while (!Thread.currentThread().isInterrupted()) {
synchronized (lock) {
DialogDescription dd = null;
boolean empty = false;
while ((dd = currentDialog) != null || (empty = dialogs.isEmpty())) {
log.info("wait, currentDialog {}, dialogs.isEmpty() {}", dd, empty);
lock.wait();
}
DialogDescription dialog = dialogs.pollFirst();
log.info("Show dialog with id {}", dialog.request().id());
currentDialog = dialog;
processAPI.runProcess(null, dialogProcess, dialog);
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
Thread.currentThread().interrupt();
}
}
public void closeDialog(String id) {
synchronized (lock) {
DialogDescription current = currentDialog;
if (current == null) {
return;
}
if (current.request().id().equals(id)) {
log.info("Close current dialog with id {}", id);
currentDialog = null;
processAPI.endProcess(dialogProcess, null);
log.info("notify close current");
lock.notify();
return;
}
if (dialogs.removeIf(d -> d.request().id().equals(id))) {
log.info("Close waiting dialog with id {}, removed from dialogs.", id);
return;
}
log.warn("Trying to close not existing dialog, {}", id);
}
}
public void showDialog(RequestInformationFromUser r, Consumer<UserInformationInputCompleted> answerCallback) {
synchronized (lock) {
boolean callAttendant = callAttendant(r);
log.info("Dialog adding to queue, dialogId={}", r.id());
dialogs.add(new DialogDescription(r, answerCallback, callAttendant));
log.info("notify show");
lock.notify();
}
}
private boolean callAttendant(RequestInformationFromUser request) {
return UserInformationType.REQUEST_AGE_CONFIRMATION == request.type() && Objects.isNull(request.requestAttendant());
}
public String getNextDialogId() {
return String.valueOf(dialogId.getAndIncrement());
}
public void setDialogProcess(DialogProcess dialogProcess) {
this.dialogProcess = dialogProcess;
}
public void reset() {
synchronized (lock) {
log.info("Reset dialog manager state");
dialogs.clear();
currentDialog = null;
processAPI.endProcess(dialogProcess, null);
lock.notify();
}
}
public boolean isDialogExist(String dialogId) {
return dialogs.stream().anyMatch(dd -> dd.request().id().equals(dialogId)) || currentDialog.request().id().equals(dialogId);
}
}
Editor is loading...
Leave a Comment