alexlcdee пре 8 година
родитељ
комит
1ea8cfa22d
9 измењених фајлова са 102 додато и 54 уклоњено
  1. 4 1
      build/.env
  2. 7 1
      src/Api.ts
  3. 1 1
      src/App.ts
  4. 16 8
      src/ChatApi.ts
  5. 32 26
      src/Client.ts
  6. 20 14
      src/Conversation.ts
  7. 10 0
      src/Interfaces.ts
  8. 11 2
      src/Log.ts
  9. 1 1
      src/main.ts

+ 4 - 1
build/.env

@@ -1,3 +1,6 @@
 MODE=prod
 HOST=127.0.0.1
-PORT=5000
+PORT=5000
+API_HOST=galapsy.ru
+API_PORT=80
+API_ENDPOINT_PREFIX=/api

+ 7 - 1
src/Api.ts

@@ -2,6 +2,8 @@ import {Interfaces} from "./Interfaces";
 
 export namespace Api {
 
+    import LoggerInterface = Interfaces.LoggerInterface;
+
     export class NullConnector implements Interfaces.ApiConnectorInterface {
         execute(endpointPath: string, data: any): Promise<string> {
             return new Promise((resolve, reject) => {
@@ -14,15 +16,19 @@ export namespace Api {
         private host: string;
         private port: number;
         private pathPrefix: string;
+        private logger: Interfaces.LoggerInterface;
 
-        constructor(host: string, port: number, pathPrefix: string = '') {
+        constructor(host: string, port: number, pathPrefix: string = '', logger: LoggerInterface) {
             this.host = host;
             this.port = port;
             this.pathPrefix = pathPrefix;
+            this.logger = logger;
         }
 
         execute(path: string, data: any): Promise<string> {
             return new Promise((resolve, reject) => {
+                this.logger.debug('Querying API: '+this.host+':'+this.port+this.pathPrefix+path);
+                this.logger.debug('With data: '+JSON.stringify(data));
                 let client = require('http').request({
                     host: this.host,
                     port: this.port,

+ 1 - 1
src/App.ts

@@ -27,7 +27,7 @@ export class App {
             });
         });
 
-        console.log(`Server started at ${config.host}:${config.port}`);
+        this.logger.info(`Server started at ${config.host}:${config.port}`);
         this.logger.debug(`App started in debug mode`);
     }
 }

+ 16 - 8
src/ChatApi.ts

@@ -22,13 +22,13 @@ export namespace ChatApi {
         processRequest(request: HTTP.IncomingMessage, response: HTTP.ServerResponse) {
             let path = url.parse(request.url).pathname;
             if (this.routes.hasOwnProperty(path)) {
-                this.logger.debug(`Processing action ${path}`);
+                this.logger.debug(`Processing action "${path}"`);
                 let action = this.routes[path];
                 action.call(this, request, response);
             } else {
-                this.logger.debug(`Action ${path} not found`);
+                this.logger.debug(`Action "${path}" not found`);
                 response.writeHead(404);
-                response.end(`Action ${path} not found`);
+                response.end(`Action "${path}" not found`);
             }
         }
 
@@ -37,15 +37,23 @@ export namespace ChatApi {
             request.on('data', (chunk) => {
                 content += chunk;
             }).on('end', () => {
-                let data = JSON.parse(content);
-                this.clientsManager.get(data.id, true).then((client: Interfaces.ClientInterface) => {
-                    response.end('Ok');
-                }).catch((err: Error) => {
+                try {
+                    let data = JSON.parse(content);
+                    this.clientsManager.get(data.id, true).then((client: Interfaces.ClientInterface) => {
+                        response.end('Ok');
+                    }).catch((err: Error) => {
+                        this.logger.error(err.message);
+                        this.logger.error(err.stack);
+                        response.writeHead(500, {'Content-type': 'text/plain'});
+                        response.end(err.message + err.stack);
+                    });
+                } catch (err) {
                     this.logger.error(err.message);
                     this.logger.error(err.stack);
+                    this.logger.error('DATA: '+content);
                     response.writeHead(500, {'Content-type': 'text/plain'});
                     response.end(err.message + err.stack);
-                });
+                }
             });
         }
     }

+ 32 - 26
src/Client.ts

@@ -41,15 +41,17 @@ export namespace Clients {
 
         private create(id: string): Promise<Interfaces.ClientInterface> {
             return new Promise((resolve, reject) => {
-                this.apiConnector.execute('/user', {id: id, action: 'getinfo'}).then((response: string) => {
-                    try {
-                        let data = JSON.parse(response);
-                        this.clients[id] = new Client(this.apiConnector, this, this.conversationsManager, this.logger, data);
-                        resolve(this.clients[id]);
-                    } catch (err) {
-                        reject(err);
-                    }
-                }, reject);
+                this.apiConnector.execute('/user', {id: id, action: 'getinfo'})
+                    .then((response: string) => {
+                        try {
+                            let data = JSON.parse(response);
+                            this.clients[id] = new Client(this.apiConnector, this, this.conversationsManager, this.logger, data);
+                            resolve(this.clients[id]);
+                        } catch (err) {
+                            reject(err);
+                        }
+                    })
+                    .catch(reject);
             });
         }
 
@@ -59,18 +61,12 @@ export namespace Clients {
                 client.status = true;
             }
 
-            if (!this.clients.hasOwnProperty(data.id)) {
-                this.create(data.id).then((client: Client) => {
-                    this.clients[data.id] = client;
-                    this.clients[data.id].addSocket(socket);
-                    setStatus(this.clients[data.id], this.logger);
-                }, (error: Error) => {
-                    console.log(error.message);
-                });
-            } else {
-                this.clients[data.id].addSocket(socket);
-                setStatus(this.clients[data.id], this.logger);
-            }
+            this.get(data.id).then((client: Client) => {
+                client.addSocket(socket);
+            }, (error: Error) => {
+                console.log(error.message);
+                console.log(error.stack);
+            });
         }
 
         get(id: string, refresh: boolean = false): Promise<Interfaces.ClientInterface> {
@@ -81,7 +77,7 @@ export namespace Clients {
                     resolve(this.clients[id]);
                 } else {
                     this.logger.debug(`Load client with ID=${id} by API call`);
-                    this.create(id).then((client: Client) => {
+                    return this.create(id).then((client: Client) => {
                         resolve(client);
                     }, reject);
                 }
@@ -141,6 +137,7 @@ export namespace Clients {
         set status(value: boolean) {
             this.api.execute('/user', {id: this.id, action: 'setstatus', value: value});
             this.isOnline = value;
+            this.logger.debug(`Status of client with ID=${this.id} is now "${this.isOnline ? 'Online' : 'Offline'}"`);
         }
 
         get name() {
@@ -156,18 +153,19 @@ export namespace Clients {
         }
 
         constructor(api: Interfaces.ApiConnectorInterface, clientsManager: Interfaces.ClientsManagerInterface, conversationsManager: Interfaces.ConversationsManagerInterface, logger: Interfaces.LoggerInterface, data: MessagingClientData) {
+            this.logger = logger;
+            this.id = data.id;
+            this.logger.debug(`Calling Client.constructor for ID=${this.id}`);
             this.api = api;
             this.clientsManager = clientsManager;
             this.conversationsManager = conversationsManager;
-            this.logger = logger;
-            this.status = true;
-            this.id = data.id;
             this.clientPhoto = data.photo;
             this.clientName = data.name;
             this.payedTime = parseInt(data.payedTime);
             this.timeToPay = data.timeToPay;
             this._coefficient = parseInt(data.coefficient);
             setInterval(this.releaseQueue.bind(this), 10000);
+            this.status = true;
         }
 
         private releaseQueue() {
@@ -179,7 +177,6 @@ export namespace Clients {
         }
 
         private sendToSockets(event: string, data: {} = {}) {
-            this.logger.debug(`Send event "${event}" to client with ID=${this.id}`);
             for (let i in this.sockets) {
                 if (this.sockets.hasOwnProperty(i)) {
                     (function (i) {
@@ -192,7 +189,9 @@ export namespace Clients {
         }
 
         addSocket(socket: SocketIO.Socket) {
+            this.logger.debug(`Add new socket for client with ID=${this.id}`);
             this.sockets.push(socket);
+            this.logger.debug(`Client with ID=${this.id} now has ${this.sockets.length} sockets`);
             let id = this.sockets.length - 1;
             socket.on('disconnect', (data) => {
                 this.onDisconnect(id);
@@ -205,9 +204,14 @@ export namespace Clients {
         }
 
         send(event: string, data: {} = {}) {
+            this.logger.debug(`Send event "${event}" to client with ID=${this.id}`);
+            this.logger.debug(`${this.sockets.length} sockets available for client with ID=${this.id}`);
             if (this.sockets.length > 0) {
+                this.logger.debug(`Sending to sockets`);
                 this.sendToSockets(event, data);
             } else {
+                this.logger.debug(`No sockets available for client with ID=${this.id}`);
+                this.logger.debug(`Pushing to queue`);
                 this.messageQueue.push(new SocketMessage(event, data));
             }
         }
@@ -221,7 +225,9 @@ export namespace Clients {
         }
 
         private onDisconnect(id) {
+            this.logger.debug(`Socket ${id} of client with ID=${this.id} is disconnected`);
             this.sockets.splice(id, 1);
+            this.logger.debug(`Client with ID=${this.id} now has ${this.sockets.length} sockets`);
             if (this.sockets.length === 0) {
                 this.status = false;
                 for (let id in this.conversations) {

+ 20 - 14
src/Conversation.ts

@@ -2,6 +2,8 @@ import {Interfaces} from "./Interfaces";
 
 export module Conversations {
 
+    import ClientInterface = Interfaces.ClientInterface;
+
     export class NullManager implements Interfaces.ConversationsManagerInterface {
         get(id: string): Promise<Interfaces.ConversationInterface> {
             return undefined;
@@ -42,8 +44,10 @@ export module Conversations {
                     this.apiConnector.execute('/conversations', {action: 'get', id: id})
                         .then((response: string) => {
                             let data = JSON.parse(response);
-                            this.clientsManager.get(data.initiatorId).then(initiator => {
-                                this.clientsManager.get(data.recipientId).then(recipient => {
+                            Promise.all([this.clientsManager.get(data.initiatorId), this.clientsManager.get(data.recipientId)])
+                                .then((values: [ClientInterface, ClientInterface]) => {
+                                    let initiator = values[0];
+                                    let recipient = values[1];
                                     let conversation = new Conversation(this.apiConnector, initiator, recipient, this.logger, data.id);
                                     conversation.duration = parseInt(data.duration);
                                     if (data.isStarted == 1 && data.isFinished == 0) {
@@ -51,8 +55,7 @@ export module Conversations {
                                     }
                                     this.add(conversation);
                                     resolve(this.conversations[id]);
-                                });
-                            });
+                                }).catch(reject);
                         }).catch(reject);
                 }
             });
@@ -61,19 +64,20 @@ export module Conversations {
         create(initiator: Interfaces.ClientInterface, recipient: Interfaces.ClientInterface): Promise<Interfaces.ConversationInterface> {
             this.logger.debug(`Create new conversation`);
             return new Promise((resolve, reject) => {
-                this.apiConnector.execute('/conversations', {action: 'create'})
+                return this.apiConnector.execute('/conversations', {action: 'create'})
                     .then(response => {
                         let data = JSON.parse(response);
-                        this.apiConnector.execute('/conversations', {
+                        return this.apiConnector.execute('/conversations', {
                             action: 'init',
                             id: data.id,
                             peers: [initiator.id, recipient.id]
-                        }).then(response => {
-                            let data = JSON.parse(response);
-                            let conversation = new Conversation(this.apiConnector, initiator, recipient, this.logger, data.id);
-                            this.add(conversation);
-                            resolve(conversation);
-                        }).catch(reject);
+                        });
+                    })
+                    .then(response => {
+                        let data = JSON.parse(response);
+                        let conversation = new Conversation(this.apiConnector, initiator, recipient, this.logger, data.id);
+                        this.add(conversation);
+                        resolve(conversation);
                     })
                     .catch(reject);
             });
@@ -216,8 +220,8 @@ export module Conversations {
             this.interval = null;
             clearInterval(this.syncInterval);
             this.syncInterval = null;
-            this.initiator.send('chat-conversation-stop', {id: this.id});
-            this.recipient.send('chat-conversation-stop', {id: this.id});
+            this.initiator.send('chat-conversation-pause', {id: this.id});
+            this.recipient.send('chat-conversation-pause', {id: this.id});
         }
 
         private setStopped() {
@@ -234,6 +238,8 @@ export module Conversations {
                 action: 'updatetime', id: this.recipient.id,
                 value: this.recipient.payedTime
             });
+            this.initiator.send('chat-conversation-stop', {id: this.id});
+            this.recipient.send('chat-conversation-stop', {id: this.id});
         }
 
         private getPeer(id): Interfaces.ClientInterface {

+ 10 - 0
src/Interfaces.ts

@@ -5,6 +5,8 @@ export module Interfaces {
         debug(message);
 
         error(message);
+
+        info(message);
     }
 
     export interface ApiConnectorInterface {
@@ -138,4 +140,12 @@ export module Interfaces {
     export interface ServerInterface {
         processRequest(request: HTTP.IncomingMessage, response: HTTP.ServerResponse);
     }
+
+    export interface MediatorInterface {
+        getClient(id: string): Promise<ClientInterface>
+        getClient(id: string, refresh: boolean): Promise<ClientInterface>
+
+        getConversation(id: string): Promise<ConversationInterface>;
+        createConversation(initiator: ClientInterface, recipient: ClientInterface): Promise<ConversationInterface>;
+    }
 }

+ 11 - 2
src/Log.ts

@@ -11,12 +11,21 @@ export namespace Log {
 
         debug(message) {
             if (this.mode.isEqualsTo(Interfaces.AppMode.DEV())) {
-                console.log(`\x1b[30m\x1b[43m%s\x1b[0m: %s`, '[DEBUG]', message);
+                console.log(`\x1b[30m\x1b[43m%s\x1b[0m[%s]: %s`, '[DEBUG]', this.getDate(), message);
             }
         }
 
         error(message) {
-            console.log(`\x1b[30m\x1b[41m%s\x1b[0m: %s`, '[ERROR]', message);
+            console.log(`\x1b[30m\x1b[41m%s\x1b[0m[%s]: %s`, '[ERROR]', this.getDate(), message);
+        }
+
+        info(message) {
+            console.log(`\x1b[32m\x1b[40m%s\x1b[0m[%s]: %s`, '[INFO ]', this.getDate(), message);
+        }
+
+        private getDate() {
+            let date = (new Date);
+            return date.toUTCString();
         }
 
     }

+ 1 - 1
src/main.ts

@@ -11,7 +11,7 @@ require('dotenv').config({path: __dirname + "/.env"});
 
 let logger = new Log.ConsoleLogger(Interfaces.AppMode.create(process.env.MODE));
 try {
-    let apiConnector = new Api.DefaultConnector('galapsy.ru', 80, '/api');
+    let apiConnector = new Api.DefaultConnector(process.env.API_HOST, process.env.API_PORT, process.env.API_ENDPOINT_PREFIX, logger);
     let clientsManager = new Clients.NullManager();
     let conversationsManager = new Conversations.DefaultManager(apiConnector, clientsManager, logger);
     clientsManager = new Clients.DefaultManager(apiConnector, conversationsManager, logger);