mirror of
				https://github.com/avatao-content/frontend-tutorial-framework
				synced 2025-11-04 05:12:54 +00:00 
			
		
		
		
	Move message queue logic to backend
This commit is contained in:
		
				
					committed by
					
						
						therealkrispet
					
				
			
			
				
	
			
			
			
						parent
						
							1b53ac40f2
						
					
				
				
					commit
					f63cede5d5
				
			@@ -7,6 +7,7 @@ export interface MessageConfig extends WebSocketMessage {
 | 
			
		||||
export interface MessageMetadata {
 | 
			
		||||
  originator?: string;
 | 
			
		||||
  timestamp?: Date;
 | 
			
		||||
  typing?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface MessageData extends MessageMetadata {
 | 
			
		||||
@@ -14,7 +15,3 @@ export interface MessageData extends MessageMetadata {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface Message extends MessageData, WebSocketMessage {}
 | 
			
		||||
 | 
			
		||||
export interface MessageQueue extends WebSocketMessage {
 | 
			
		||||
    value: Array<MessageData>;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								src/app/message-types/deploy-message.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/app/message-types/deploy-message.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
import { WebSocketMessage } from './websocket-message';
 | 
			
		||||
 | 
			
		||||
export interface DeployMessage extends WebSocketMessage {
 | 
			
		||||
  status: string;
 | 
			
		||||
}
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="tfw-grid-message-body" [innerHtml]="message.message"></div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div *ngIf="messageInQueue" class="tfw-grid-message jumping-circle-container">
 | 
			
		||||
  <div *ngIf="showTypingIndicator" class="tfw-grid-message jumping-circle-container">
 | 
			
		||||
      <div class="jumping-circle" id="jc1"></div>
 | 
			
		||||
      <div class="jumping-circle" id="jc2"></div>
 | 
			
		||||
      <div class="jumping-circle" id="jc3"></div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
import { ChangeDetectorRef, Component, OnInit, EventEmitter, Output } from '@angular/core';
 | 
			
		||||
import { MessageConfig, MessageData, Message, MessageQueue } from '../message-types/bot-messages';
 | 
			
		||||
import { MessageConfig, MessageData, Message } from '../message-types/bot-messages';
 | 
			
		||||
import { MarkdownService } from '../services/markdown.service';
 | 
			
		||||
import { WebSocketService } from '../services/websocket.service';
 | 
			
		||||
 | 
			
		||||
@@ -14,42 +14,31 @@ import { Subject, Observer, BehaviorSubject } from 'rxjs';
 | 
			
		||||
export class MessagesComponent implements OnInit {
 | 
			
		||||
  @Output() newMessageEvent: EventEmitter<any> = new EventEmitter();
 | 
			
		||||
  newMessage: Subject<MessageData> = new Subject<MessageData>();
 | 
			
		||||
  messageInQueue = true;
 | 
			
		||||
  showTypingIndicator = false;
 | 
			
		||||
 | 
			
		||||
  originator = 'avataobot';
 | 
			
		||||
  messages: MessageData[] = [];
 | 
			
		||||
  messageQueueAttender: MessageQueueAttender;
 | 
			
		||||
 | 
			
		||||
  command_handlers = {
 | 
			
		||||
    'message.queue': this.handleQueueMessage.bind(this),
 | 
			
		||||
    'message.config': this.configureMessages.bind(this),
 | 
			
		||||
    'message.send': () => {}
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private markdownService: MarkdownService,
 | 
			
		||||
    private websocketService: WebSocketService,
 | 
			
		||||
    private changeDetectorRef: ChangeDetectorRef
 | 
			
		||||
  ) {
 | 
			
		||||
    this.messageQueueAttender = new MessageQueueAttender(this.newMessage);
 | 
			
		||||
  }
 | 
			
		||||
  ) {}
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    this.newMessage.subscribe(
 | 
			
		||||
      message => {
 | 
			
		||||
        this.showTypingIndicator = true;
 | 
			
		||||
        this.writeMessage(message);
 | 
			
		||||
        this.newMessageEvent.emit();
 | 
			
		||||
    });
 | 
			
		||||
    this.messageQueueAttender.messageInQueue.subscribe(
 | 
			
		||||
      (value) => this.messageInQueue = value
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    this.websocketService.connect();
 | 
			
		||||
    this.websocketService.observeKey<Message>('message.send').subscribe(
 | 
			
		||||
      message => this.newMessage.next(message)
 | 
			
		||||
    );
 | 
			
		||||
    this.websocketService.observeKey<MessageQueue>('message').subscribe(
 | 
			
		||||
      message => this.command_handlers[message.key](message)
 | 
			
		||||
    this.websocketService.observeKey<MessageConfig>('message.config').subscribe(
 | 
			
		||||
      message => this.configureMessages(message)
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -67,10 +56,7 @@ export class MessagesComponent implements OnInit {
 | 
			
		||||
    if (!message.timestamp) {
 | 
			
		||||
      message.timestamp = new Date();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleQueueMessage(message: MessageQueue) {
 | 
			
		||||
    this.messageQueueAttender.queueMessages(message.value);
 | 
			
		||||
    this.showTypingIndicator = message.typing;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  configureMessages(message: MessageConfig) {
 | 
			
		||||
@@ -83,48 +69,3 @@ export class MessagesComponent implements OnInit {
 | 
			
		||||
    return this.markdownService.convertToHtml(text);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class MessageQueueAttender {
 | 
			
		||||
  public messageInQueue = new BehaviorSubject<boolean>(false);
 | 
			
		||||
 | 
			
		||||
  private readonly charPerSecond: number;
 | 
			
		||||
  private lastMessageLength = 0;
 | 
			
		||||
  private queue: MessageData[] = [];
 | 
			
		||||
 | 
			
		||||
  constructor(private messageEmitter: Observer<MessageData>, wordPerMinute: number = config.messages.messageQueueWPM) {
 | 
			
		||||
    const charPerMinute = wordPerMinute * 5;
 | 
			
		||||
    this.charPerSecond = charPerMinute / 60;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  queueMessages(messages: Array<MessageData>) {
 | 
			
		||||
    this.queue = this.queue.concat(messages);
 | 
			
		||||
    this.attendQueue();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private processMessage() {
 | 
			
		||||
    if (this.queue.length > 0) {
 | 
			
		||||
      const lastMessage = this.queue.shift();
 | 
			
		||||
      this.lastMessageLength = lastMessage.message.length;
 | 
			
		||||
      this.messageEmitter.next(lastMessage);
 | 
			
		||||
    }
 | 
			
		||||
    if (this.queue.length === 0) {
 | 
			
		||||
      this.lastMessageLength = 0;
 | 
			
		||||
      this.messageInQueue.next(false);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private attendQueue() {
 | 
			
		||||
    if (this.queue.length > 0) {
 | 
			
		||||
      this.messageInQueue.next(true);
 | 
			
		||||
      const timeoutSeconds = this.lastMessageLength / this.charPerSecond;
 | 
			
		||||
      setTimeout(
 | 
			
		||||
        () => {
 | 
			
		||||
          this.processMessage();
 | 
			
		||||
          this.attendQueue();
 | 
			
		||||
        },
 | 
			
		||||
        timeoutSeconds * 1000
 | 
			
		||||
      );
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user