I have two applications that I need to synchronise. One of them will receive data from users and the other will display the data. Both applications will work on different servers. They could be disconnected at some times and they need to continue working until reconnect, so I will replicate the data from the first application on the second application.
On Meteor documentation I found DDP.connect(url)but I'm not sure how to use it. I found many questions and examples connecting non Meteor applications with Meteor using DDP, but nothing about connecting two Meteor applications.
My first approach was something like this:
Application 1
Items = new Meteor.Collection('items');
Items.insert({name: 'item 1'});
if (Meteor.isServer) {
Meteor.publish('items', function() {
return Items.find();
});
}
Application 2
Items = new Meteor.Collection('items')
if (Meteor.isServer) {
var remote = DDP.connect('http://server1.com/);
remote.onReconnect = function() {
remote.subscribe('items');
var items = Items.find();
console.log(items.count()); // expected to be 1 but get 0
}
}
On the second application, how can I get the items from the first application?
I got a clue from this question How to properly use Meteor.connect() to connect with another Meteor server. I missed it because it was about the old Meteor.connect() that changed to DDP.connect().
This worked on client and server
var remote = DDP.connect('http://server1.com/');
Items = new Meteor.Collection('items', remote);
remote.subscribe('items', function() {
var items = Items.find();
console.log(items.count()); // get 1
});
Now I can watch for changes in application 1 from application 2 using Items.find().observe()
Warning
There is a bug on Meteor that will stop the connection between applications:
https://github.com/meteor/meteor/issues/1543
DDP between two servers doesn't reconnect
Update
The bug was solved
Update 2
This is a sample project tested with Meteor 0.6.6.2 https://github.com/camilosw/ddp-servers-test
Related
my blazor app seems to work but im trying to understand why I'm getting a 400error as seen in the screenshot.
Who can give me a HINT for what Blazor needs technically the "disconnect" ?
SCREENSHOT-disconnect
I'm running everything on a NGINX webserver.
thx Fabio
That call happens here in the code on the window unload event and is used to tell the signalr server that you are disconnecting.
If you are seeing a lot of these it may be that your proxy is not configured correctly for websocket connections.
window.addEventListener(
'unload',
() => {
const data = new FormData();
const circuitId = circuit.circuitId!;
data.append('circuitId', circuitId);
navigator.sendBeacon('_blazor/disconnect', data);
},
false
);
There's a bug reported for this issue here:
https://github.com/dotnet/aspnetcore/issues/30316
Blazor.server.js not respecting configureSignalR builder defined
url/path for disconnnects
As a work-around, I added this to Startup.cs in the Configure method:
var rewriteOptions = new RewriteOptions();
rewriteOptions.AddRewrite("_blazor/disconnect", "/_blazor/disconnect", skipRemainingRules: true);
app.UseRewriter(rewriteOptions);
I know that there are several methods to share collections on both the client and server -- namely either in top level lib folder or publish/subscribe model -- but when I try either of these things when using mongodb running at localhost:27017 as my MONGO_URL, I am not reliably getting data on the client. Occasionally console.log(myCollection.findOne({})) will return expected data in the browser but most of the time it returns undefined.
//Client side code
Template.controls.onCreated(function controlsOnCreated() {
Meteor.subscribe("myEvents");
Events = new Mongo.Collection("events");
});
//Server side code
Meteor.startup(() => {
Events = new Mongo.Collection("events");
}
Meteor.publish('myEvents', function() {
console.log(Events.find());
return Events.find();
});
UPDATED CODE -- returns Events on server but not client:
//Client
Template.controls.onCreated(function controlsOnCreated() {
this.subscribe("myEvents");
});
//Server
if (Meteor.isServer) {
Meteor.publish("myEvents", function() {
return Events.find();
});
}
// /collections/events.js
Events = new Mongo.Collection("events");
UPDATE 2:
I am attempting to verify the publication in the browser after the page has rendered, calling Events.findOne({}) in the Chrome dev tools console.
on your client:
Template.controls.onCreated(function controlsOnCreated() {
Meteor.subscribe("myEvents");
Events = new Mongo.Collection("events");
});
that is an odd place to define the Events variable. typically, you would put that line of code in a JS file common to both platform. e.g.
collections/events.js:
Events = new Mongo.Collection("events");
when that line runs on the server, it defines the mongo collection and creates a server-side reference to it. when it runs on the client, it creates a collection by that name in mini-mongo and creates a client-side reference to it.
you can write your onCreated like this (note "this" instead of "Meteor"):
Template.controls.onCreated(function() {
this.subscribe("myEvents");
});
you don't say where on the client you ran your console.log with the find(). if you did it in the onCreated(), that's too early. you're seeing the effects of a race condition. typically, you might use it in a helper:
Template.controls.helpers({
events() {
return Events.find({});
}
});
and display the data in the view:
{{#each event in events}}
{{event.name}}
{{/each}}
that helper will run reactively once the data from the publish shows up.
I'm using Angular 2 to send requets to my Laravel PHP API and show them in my client.
So far, I used the following code to check for new updates from the server and update my data (making an API call in interval of 3 seconds):
ngOnInit()
{
this.dataRefresh = setInterval(() => {
this.dataInit();
}, 3000);
}
dataInit()
{
this.http.get('APICALL')
.map((res:Response) => res.json())
.subscribe(
data => {
this.data = data;
},
err => {
console.error(err);
});
}
Now I'm thinking further. Let's say 50 computers are connected in the same time to my app. Each of them making an API call every 3 seconds, which means the server will have to handle about 16 requests every second.
My question is:
Can I handle this scenario using Angular 2 / Laravel?
If no, what's the current way to do this?
Thanks in advance.
You can use a real time database like firebase.
Instead of your clients asking for updates to your API every second, your API will let know the clients when there is any update.
You can find firebase tutorials here & here.
There are also some packages available like angular2-firebase and angularfire2 to help your Angular2 app connect to your firebase db easily.
I'm trying to publish all emails and "roles" to "admin" users (using the meteor-roles meteorite package), and the server knows what it's trying to publish, but for some reason the client is not picking up the data. Here's the piece of code involved:
Server Code:
Meteor.publish("directory", function() {
if(Roles.userIsInRole(this.userId, 'admin')) {
//next line shows that it outputs that there are 2 documents in this
console.log(Meteor.users.find({}, {fields:{emails:1, roles:1}}).count());
return Meteor.users.find({}, {fields:{emails:1, roles:1}});
} else {
return {};
}
}
Client Code:
Meteor.subscribe("directory");
Directory = new Meteor.Collection("directory");
//and then to simulate my use for this collection
console.log(Directory.find().count());
//which outputs 0
Why isn't the client getting the documents? (and I am definitely logging in with an account with role "admin")
Thanks!
EDIT and SOLUTION!
Okay, so I figured out what I was doing wrong. I just need to publish "directory" on the server, and subscribe on the client. Then, all user data goes into the Meteor.users collection, and I shouldn't define my own "Directory=new Meteor.Collection('directory')". I can then access the data via Meteor.users. Cheers!
Server: use same code as above
Client:
Meteor.subscribe("directory");
console.log(Meteor.users.find().count()); //outputs 2, yay!
Your collection should probably be defined on the beginning so that client knows where to write!
Also, your Meteor.subscribe("directory"); runs once when the app is loaded. You should make it reactive.
Directory = new Meteor.Collection("directory");
Deps.autorun(function(){
Meteor.subscribe("directory");
});
On the server side I want to publish only the data that concerns the current day.
This is my code on the server :
Meteor.publish('myData', function() {
var today = new Date();
today.setSeconds(0);
today.setMinutes(0);
today.setHours(0);
var tomorrow = new Date();
tomorrow.setSeconds(59);
tomorrow.setMinutes(59);
tomorrow.setHours(23);
return MyData.find({mTime : {$gt:today.getTime(), $lt:tomorrow.getTime()}});
});
The problem is that it seems this code is launched only when i deploy the app on the server.
So it is only getting the day of the deployment.
How can i get my app to republish the collection on accessing the app or on reload ?
Thanks
Try to place your subscribe code into Meteor.startup() function on the client side.
e.g.
if(Meteor.isClient){
Meteor.startup(function(){
Meteor.subscribe('myData');
});
}
This will re-subscribe the myData whenever the app is reloaded or refreshed.