I've just started angular 2. I've done an angular2 sample as given in the https://angular.io/guide/quickstart
when I run the project in Firefox using
npm start
command in terminal, the connection get disconnected after output showing once.Error showing like
The connection to ws://localhost:3000/browser-sync/socket.io/?EIO=3&transport=websocket&sid=6YFGHWy7oD7T7qioAAAA was interrupted while the page was loading
Any idea about how to fix this issue ?
I don't know how you manage your web socket but you could consider using the following code. This idea is to wrap the web socket into an observable.
For this you could use a service like below. The initializeWebSocket will create a shared observable (hot) to wrap a WebSocket object.
export class WebSocketService {
initializeWebSocket(url) {
this.wsObservable = Observable.create((observer) => {
this.ws = new WebSocket(url);
this.ws.onopen = (e) => {
(...)
};
this.ws.onclose = (e) => {
if (e.wasClean) {
observer.complete();
} else {
observer.error(e);
}
};
this.ws.onerror = (e) => {
observer.error(e);
}
this.ws.onmessage = (e) => {
observer.next(JSON.parse(e.data));
}
return () => {
this.ws.close();
};
}).share();
}
}
You could add a sendData to send data on the web socket:
export class WebSocketService {
(...)
sendData(message) {
this.ws.send(JSON.stringify(message));
}
}
The last point is to make things a bit robust, i.e. filter received messages based on a criteria and implement retry when there is a disconnection. For this, you need to wrap our initial websocket observable into another one. This way we can support retries when the connection is lost and integrate filtering on criteria like the client identifier (in the sample the received data is JSON and contains a sender attribute).
export class WebSocketService {
(...)
createClientObservable(clientId) {
return Observable.create((observer) => {
let subscription = this.wsObservable
.filter((data) => data.sender!==clientId)
.subscribe(observer);
return () => {
subscription.unsubscribe();
};
}).retryWhen((errors) => {
return Observable.timer(3000);
});
}
}
You can see that deconnections are handled in this code using the retryWhen operator of observable.
Related
I'm here to request help with mongo/mongoose. I use AWS lambda that accesses a mongo database and I'm having problems sometimes my connections reach the limit of 500. I'm trying to fix this problem and I did some things like this https://dzone.com/articles/how-to-use-mongodb-connection-pooling-on-aws-lambd and https://www.mongodb.com/blog/post/optimizing-aws-lambda-performance-with-mongodb-atlas-and-nodejs. That basically is to use a singleton-like and set context.callbackWaitsForEmptyEventLoop = false, which indeed helped but is still, rarely, open 100 connections in less than a minute, it looks like there is some connection that is not being reused even tho our logs show that they are being reused. So I realized a weird behavior, whenever mongoatlas shows me an increased number of commands, my mongo connections increase heavily. The first chart is operations and the second is the connections.
Looking at operations, there are too many commands and just a few queries. I have no idea what are those commands, my theory is that those commands are causing the problem but I did not find anything that explained what is the difference between query and command exactly for me to know if that is a valid theory or not. Another thing is, how to choose correctly the number of pool size, we have really simple queries.
Here is our singleton class because maybe this is what we are doing wrong:
class Database {
options: [string, mongoose.ConnectionOptions];
instance?: typeof mongoose | null;
constructor(options = config) {
console.log('[DatabaseService] Created database instance...');
this.options = options;
this.instance = null;
}
async checkConnection() {
try {
if (this.instance) {
const pingResponse = await this.instance.connection.db.admin().ping();
console.log(`[DatabaseService] Connection status: ${pingResponse.ok}`);
return pingResponse.ok === 1;
}
return false;
} catch (error) {
console.log(error);
return false;
}
}
async init() {
const connectionActive = await this.checkConnection();
if (connectionActive) {
console.log(`[DatabaseService] Already connected, returning instance`);
return this.instance;
}
console.log('[DatabaseService] Previous connection was not active, creating new connection...');
this.instance = await mongoose.connect(...this.options);
const timeId = Date.now();
console.log(`Connection opened ${timeId}`);
console.time(`Connection started at ${timeId}`);
this.instance?.connection.on('close', () => {
console.timeEnd(`Connection started at ${timeId}`);
console.log(`Closing connection ${timeId}`);
});
return this.instance;
}
async getData(id: string) {
await this.init();
const response = await Model.findOne({ 'uuid': id });
return response;
}
}
I hope that is enough information. My main question is if my theory of commands causing too many connections is possible and what are exactly commands because every explanation that I found look like is the same than query.
Based on the comment written by Matt I have changed my init function and now my connections are under control.
async init() {
if (this.instance) {
console.log(`[DatabaseService] Already connected, returning instance`);
return this.instance;
}
console.log('[DatabaseService] Previous connection was not active, creating new connection...');
this.instance = await mongoose.connect(...this.options);
const timeId = Date.now();
console.log(`Connection opened ${timeId}`);
console.time(`Connection started at ${timeId}`);
this.instance?.connection.on('close', () => {
console.timeEnd(`Connection started at ${timeId}`);
console.log(`Closing connection ${timeId}`);
});
return this.instance;
}
I try to execute this code and receive current blockchain block number
nodeInteraction.currentHeight('https://nodes.wavesplatform.com/').then((res) => {
console.log(res);
});
I did not forget to import the library
import { invokeScript, broadcast, nodeInteraction, waitForTx } from '#waves/waves-transactions';
This code is executed correctly.
nodeInteraction.accountData(dappaddress, baseUri).then((v) => {
window.dAppData = v;
if (v) {
window.dAppDataKeys = Object.keys(v);
console.log("dApp Account data:");
console.log(v);
console.log(JSON.stringify(v));
}
});
I'm using below library
https://wavesplatform.github.io/waves-transactions/globals.html#currentheight
I find an answer) I forgot to re-build my React app. Sorry.
so I'm using RabbitMQ for some Projects and i noticed that i ll use some duplicate code all the Time that's why i decided to make a Wrapper Class or Interface that have some function to use RabbitMQ direct without repeating the code all the time. i began to do this yesterday and i already had some Problems since i wanted to use OOP and Javascript can be complicated when using OOP (at least i think so)
I began with creating a class IRAbbitMQ with function init to initialize a connection and create a channel, i knew that i cant use nested classes so instead i wanted to use Factory functions, i tried to make the connection and channel a part of the class IRabbitMQ properties but i dont know why that gave me undefined when i create an instance of it
class IRabbitMQ {
constructor() {
this.init(rabbitMQServer); // rabbitMQServer for example 'localhost//5672'
}
// establish a Connection to RAbbitMQ Server
async init(host) {
try {
let connection = await amqplib.connect(host);
let channel = await connection.createChannel();
channel.prefetch(1);
console.log(' [x] Awaiting RPC requests');
this.connection = connection;
this.channel = channel;
}
catch(err) {
console.error(err);
}
}
// Close the Connection with RabbitMQ
closeConnection() {
this.connection.close();
}
log() {
console.log(this.connection);
}
EventPublisher() {
function init(IRabbit, publisherName) {
if(!IRabbit.connection) {
throw new Error('Create an Instance of IRabbitMQ to establish a Connection');
}
let ch = IRabbit.channel;
console.log(ch);
}
return {
init : init
}
}
}
var r = new IRabbitMQ();
r.log();
when i run the code the output is undefined, i dont know why since i m initializing the connection and channel properties in the init function and then called that function in the constructor so that should be initialized when i create an object of the Wrapper class. i wanted also to take some advices from you wether it is good to use classes or is there any other better way to create a Wrapper class or Interface for RabbitMQ to make it easy to use it and not have to duplicate Code.
Not really an answer, but I was able to successfully log the connection with this example code. I trimmed out other code to just focus on the .log() part that was logging a undefined.
Code is far from perfect, but works at least
const amqplib = require('amqplib');
class IRabbitMQ {
constructor() { }
async init(host) {
try {
const connection = await amqplib.connect(host);
const channel = await connection.createChannel();
channel.prefetch(1);
console.log(' [x] Awaiting RPC requests');
this.connection = connection;
this.channel = channel;
}catch(err) {
console.error(err);
}
}
log() {
console.log(this.connection);
}
}
async function createInstance(){
const instance = new IRabbitMQ();
try {
await instance.init('amqp://localhost');
}catch (e) {
throw new Error('OOPS!');
}
return instance;
}
async function runLogic() {
const r = await createInstance();
r.log();
}
runLogic().catch(console.log);
Just comment if you'd want me to give additional advice/tips, but this seems to work for me.
After making a subscription from Angular service, the returning results are bunch of duplicates. For every call, the number of duplicates increase by one.
I tried console logging the results at various stages of the app. The duplicates are returned immediately after the promise get rendered
Angular Service code:
GetUserPendingApprovals(userid: string) {
let approvalsPending: any[] = [];
this.http
.get<{message, approvals: any}>(`/api/approvals/${userid}`)
.subscribe(approvals => {
console.log(approvals.approvals);
approvalsPending = approvals.approvals;
this.approvalsUpdated.next(approvalsPending);
approvalsPending = [];
});
}
getUserPendingApprovalsUpdateListener() {
return this.approvalsUpdated.asObservable();
}
node end point:
app.get("/api/approvals/:userid", (req, res, next) => {
// const urlData = req.params.userId;
//console.log(urlData);
const query = datastore
.createQuery('approvals')
.filter('src', '=', req.params.userid);
query.run().then(approvals => {
approvals.forEach(approval => console.log(approval));
console.log(approvals[0].length);
res.status(200).json(
{
message: "Request was processed successfully!",
approvals: approvals[0]
}
);
})
})
The console logging on node endpoint returns a proper count value for the results being queries for. However, console logging of the same results on the Angular service code returns duplicates and the number of duplicates increase by one for every call. Example: 1st call - 2 duplicates, 2nd call - 3 duplicates, 3rd call - 3 duplicates and so on.
More information...
I am making nested subscription from my angular component. Something like below -
ngOnInit() {
this.activatedRoute.params
.subscribe(
(params: Params) => {
....some code goes here...
this.revenueService.GetUserInvoicesThisWeek(this.userid);
this.currentWeekInvoicesSub = this.revenueService.GetUserInvoicesThisWeekListener()
.subscribe((revenueInfo: Revenue[]) => {
....some code goes here...
});
this.currentDayInvoicesSub = this.revenueService.GetUserInvoicesTodayListener()
.subscribe((todayRevenueInfo: Revenue[]) => {
....some code goes here...
});
this.approvalsService.GetUserPendingApprovals(this.userid);
this.approvalsSub = this.approvalsService.getUserApprovalsUpdateListener()
.subscribe((approvalsPending: any[]) => {
....some code goes here...
});
});
}
The last subscription is where i am facing problems. But i am pretty sure the rendered promise right after the node endpoint call is returning duplicates. Something which i mentioned in the beginning of this question.
Doubts:
What would be the root cause for these duplicates?
How to resolve this issue?
You are subscribing everytime this function gets called, so you're making a duplicate subscription everytime you change your route.
GetUserPendingApprovals(userid: string) {
let approvalsPending: any[] = [];
this.http
.get<{message, approvals: any}>(`/api/approvals/${userid}`)
.subscribe(approvals => {
console.log(approvals.approvals);
approvalsPending = approvals.approvals;
this.approvalsUpdated.next(approvalsPending);
approvalsPending = [];
});
}
Subscribe in the component instead in the service to fix this issue.
GetUserPendingApprovals(userid: string) {
return this.http
.get<{message, approvals: any}>(`/api/approvals/${userid}`)
}
Component ts:
ngOnInit(){
this.aprovalSub = this.approvalsService.GetUserPendingApprovals(this.userid);
.subscribe(approvals => {
approvalsService.approvalsPending = approvals.approvals;
approvalsService.approvalsUpdated.next(approvalsPending);
});
}
ngOnDestroy(){
if(this.aprovalSub !== undefined) this.aprovalSub.unsubscribe()
}
Clean up subscriptions when component gets destroyed or they will stay in memory and you will have subscriptions taking up memory.
I'm not sure of how to adequately achieve my desired control flow using promises/bluebird.
Essentially I have a database with X 'tasks' stored and each needs to be loaded and executed sequentially. I don't want to run more than one task concurrently and the entire code must continue executing indefinitely.
I have achieved this with the following code so far:
export default function syncLoop() {
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(syncLoop)
.catch((error) => {
throw new Error(error);
});
} else {
syncLoop();
}
});
}
getNextTaskRunner() simply loads and resolves with the next task from the database (calc'd based on timestamps). Or it resolves with null (no task avail).
taskRunner.startTask() resolves with null when the full task has completed.
I've been advised that the way it is structured (recursive /w promises) could lead to stack issues after it has been running for some time.
What I've thought about doing is to restructure it to something like:
let running = false;
setInterval(() => {
if (!running) {
running = true;
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(() => {
running = false;
})
.catch((error) => {
log.error(error);
});
} else {
running = false;
}
});
}
}, 5000);
Or as yet another possibility, using event emitters in some form?
task.on('complete', nextTask());
Thoughts and advice will be greatly appreciated!
What stack issues? The way you've written your code is perfectly fine as long as getNextTaskRunner is truly async (i.e. it gives control back to the main loop at some point, e.g. if it does async io). There is no recursion in your code in that case. Whoever told you that is mistaken.
Though you might want to add a setTimeout somewhere so you won't flood your db with requests. Plus it will help you if getNextTaskRunner will no longer be sync (due to for example in memory caching):
export default function syncLoop() {
setTimeout(() => {
getNextTaskRunner().then((taskRunner) => {
if (taskRunner) {
taskRunner.startTask()
.then(syncLoop)
.catch((error) => {
throw new Error(error);
});
} else {
syncLoop();
}
});
}, 2000);
}