How to Connect Meteor Server to External Websocket / Socket IO API? - meteor

In my Meteor 1.0 app, I'm trying to connect the server to an external websocket (socket-io) API provided by a company called BTC China. Details on the API can be found here.
All the examples I have found are for the client. How does one subscribe to a socket-io API on the Meteor server? There doesn't seem to be a meteor package for this on atmospherejs.com and I'm struggling a bit. I've installed the socket-io NPM package and gotten this far:
var socket = Npm.require('socket.io').listen('https://websocket.btcchina.com/');
socket.emit('subscribe', ['marketdata_cnybtc']);
socket.emit('subscribe', ['marketdata_cnyltc']);
socket.emit('subscribe', ['marketdata_btcltc']);
socket.on('connect', function(){
console.log("Hello,btcc!");
socket.on('trade', function (data) {
console.log("Hello,trade!");
console.log(data);});
});
But this returns the following error: TypeError: Object https://websocket.btcchina.com/ has no method 'listeners', which means I'm defining the socket variable incorrectly. How can I fix this? Thanks!

I created a new Meteor package joncursi:socket-io-client to solve this problem. Please see https://atmospherejs.com/joncursi/socket-io-client for more detail and example usage. Since I've bundled the NPM binaries into a package, so you won't have to worry about installing NPM packages, declaring NPM.require() dependencies, etc. And best of all, you can deploy to .meteor.com without a hitch.

Related

NextJS and deploying app - What's the use of the /api folder when wanting to make API calls in production (deployed)?

I just went through the steps of creating a CRUD app with NextJS. Everything works fine when I run the app on my development environment npm run dev.
Then I tried to deploy it to Vercel.
The build fails, and the error that comes up is:
AxiosError: connect ECONNREFUSED 127.0.0.1:3000
...
Build error occurred
Error: Failed to collect page data for /beers/[id]
at /vercel/path0/node_modules/next/dist/build/utils.js:963:15
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
type: 'Error'
I get it: when I make my API requests, the app is using HTTP:localhost:3000, so if deployed, it won't reach.
Then comes my question: locally, I run requests as such, for example:
import axios from 'axios';
axios.defaults.baseURL = "http://localhost:3000";
export const getAllBeers = () => axios.get<BeerData[]>('/api/beers');
and everything works.
I tried to troubleshoot my error. I figured I needed to adjust my baseUrl to the deployment server's address. But it still wouldn't work. And then in the few posts I read, and even in the docs, it says:
Write server-side code directly
As getStaticProps runs only on the server-side, it will never run on
the client-side. It won’t even be included in the JS bundle for the
browser, so you can write direct database queries without them being
sent to browsers.
This means that instead of fetching an API route from getStaticProps
(that itself fetches data from an external source), you can write the
server-side code directly in getStaticProps.
doc source
So after following their tutorial, I'm now confused on the purpose of this /api folder, and in which specific case it's useful? When we want to use the getStaticProps for example.
If anybody could explain with an example? That'd be fantastic. Thank you!

SignalR reconnect client & two different versions avaliable?

I've got a few questions and problems regarding SignalR.
1st question:
I've downloaded signalr like this: npm install #aspnet/signalr according to Npmjs (v1.0.3).
However, upon further inspection, my signalr files do not contain reconnect-functionality as can be found on the github:343 here.
As a matter of fact, it seems like these are two different repos. Why do they differ, both seem to be developed by microsoft?
these are the two repos: https://github.com/SignalR/SignalR
and https://github.com/aspnet/SignalR
2nd question:
I've tried to implement reconnect-functionality into my application with the limited functionality avaliable to me. This is my current approach (since i lack the reconnect-functions in the 1st repo) the code below produces this output on disconnect:
signalr.min.js:1353 Error: Connection disconnected with error 'Error: Server timeout elapsed without receiving a message from the server.'.
Uncaught TypeError: this.connect is not a function
at HubConnection.eval
trying to connect...
Uncaught TypeError: this.connect is not a function
at HubConnection.eval
trying to connect...
etc... etc...
Code:
this.connection.onclose(function (error) {
if (!this.isConnected) {
this.isConnected = false;
appService.emit("disconnected", true);
var intervalFunc = setInterval(function () {
console.log("trying to connect...");
this.connect();
if (this.isConnected) {
this.appService.emit("connected", true);
this.isConnected = true;
clearInterval(intervalFunc);
console.log("connection established");
}
}.bind(this), 5000);
}
});
I've also followed these resources in trying to implement reconnect-functionality:
https://stackoverflow.com/a/23407156/2902996
https://learn.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/handling-connection-lifetime-events#how-to-continuously-reconnect
https://github.com/davidfowl/UT3/blob/dac409886c1bb7aec7c150b74d4ce9a3e246f03c/UTT/wwwroot/js/utt.js#L141-L153
https://github.com/aspnet/Docs/issues/6757
Any help would be greatly appreciated.
There is a .NET version and .NET CORE version. At the top of each of the github's you linked it shows: Incredibly simple real-time web for .NET (first github) and Incredibly simple real-time web for ASP.NET Core (second GitHub).
Your second question may come down to determining if you mixed up which SignalR product (.NET or .NET CORE) and the Clients for each. They are not cross compatible, so you cannot use the .NET JS Client with the Client for .NET Core.
I would recheck what you have implemented and go from there.
If you check the .NET Core repo under issues and search for reconnect, it does appear that reconnect is not a function any longer in .NET Core. See issue 1611.

Google Cloud Datastore - Endpoint Read Failed Error

I keep getting below error every once in a while when I call the datastore.save method:
Error: Endpoint read failed at /user_code/node_modules/#google-cloud/datastore/node_modules/grpc/src/client.js
My code is running inside a Google Cloud Function and I am using the official Node.js client library provided by Google for Google Cloud Datastore.
Can someone help? Thanks in advance.
As mentioned in the comments, this appears to be an instance of this issue. That issue has since been closed because a change in the gRPC library should fix the problem.

Google Cloud Functions with Trace Agent connection

I need to connect monitoring and tracing tools for our application. Our main code is on Express 4 running on Google Cloud Functions. All requests incoming from front nginx proxy server that handle domain and pretty routes names. Unfortunately, trace agent traces this requests, that coming on nginx front proxy without any additional information, and this is not enough to collect useful information about app. I found the Stack Driver custom API, which, as I understand might help to collect appropriate data on runtime, but I don't understand how I can connect it to Google Cloud Functions app. All other examples saying, that we must extend our startup script, but Google Cloud Functions fully automated thing, there is no such possibility here.
Found solution. I included require("#google-cloud/trace-agent"); not at the top of the index.js. It should be included before all other modules. After that it started to work.
Placing require("#google-cloud/trace-agent") as the very first import didn't work for me. I still kept getting:
ERROR:#google-cloud/trace-agent: express tracing might not work as /var/tmp/worker/node_modules/express/index.js was loaded before the trace agent was initialized.
However I managed to work around it by manually patching express:
var traceApi = require('#google-cloud/trace-agent').get();
require("#google-cloud/trace-agent/src/plugins/plugin-express")[0].patch(
require(Object.keys(require('module')._cache).find( _ => _.indexOf("express") !== -1)),
traceApi
);

Background tasks not connected with any client in Meteor

I would like to run some client-independent regular tasks in the background of a Meteor app (like scraping some pages). So they should not be inside any client thread, but once they finish, I would like to update all clients with information. What is the best way to achieve this?
Run them on your server side code. If by regular you mean timed tasks every day or something:
You could use a cron job with Tom Coleman's cron package : https://github.com/tmeasday/meteor-cron.
You'll need to install the meteorite package manager first : npm install meteorite -g and then install the cron package in your project dir mrt add cron-tick
Server js
var MyCron = new Cron();
// this job will happen every day (60 seconds * 60 * 24)
MyCron.addJob(60*60*24, function() {
//Scrape your stuff
//Update your collections
});
As soon as you run your update/insert/edit they will be pushed to all clients.
To do this in a way that allows arbitrary external processes update the Meteor clients, use the DDP protocol that's associated with Meteor. Your server processes can write to the DDP channel, and when they do your clients will update. Have a look at this post for an example and a use case, which may be similar to yours:
Using node ddp-client to insert into a meteor collection from Node
The protocol is fairly straight forward, and the post shows an example of a node.js process writing to a Mongo collection that updates the clients in real time.
You could try calling a Meteor.setInterval on the server (perhaps in Meteor.startup). That should work, though it might not be as flexible as the cron solution.
Go to http://atmospherejs.com and search for cron
The best one I found is percolate:synced-cron
Installation
meteor add percolate:synced-cron
Basics
SyncedCron.add({
name: 'Crunch some important numbers for the marketing department',
schedule: function(parser) {
// parser is a later.parse object
return parser.text('every 2 hours');
},
job: function() {
var numbersCrunched = CrushSomeNumbers();
return numbersCrunched;
}
});
SyncedCron.start();
Advanced
See their documentation

Resources