Whenever I update current user, all collections are flushed (actually not) - javascript

I'm developing a website with angular-meteor and I've faced a strange problem. On every page I have a chat block, the messages are stored in collection chatMessages and displayed correctly. The problem is that every time I edit current user (manual mongo document edition or updating inside meteor's method) my app removes all subscriptions. As the result, messages disapper from the chat. But not only chat messages disappear. I used this piece of code to understand what's the cause of the problem, but I can barely understand it. Here's the most interesting parts from browser console output:
// On page load
send Object {
msg: "sub",
id: "EPgQwMiDggM7wafCN",
name: "chatMessages",
params: Array[0]
}
receive Object {
msg: "added",
collection: "chatMessages",
id: "G6tv76ZSJYXmnsrAY",
fields: Object
}
// Calling 'createArenaRoom' method
send Object {
msg: "method",
method: "createArenaRoom",
params: Array[1],
id: "8",
randomSeed: "516b5128615f1c7849f2"
}
// User updated
receive Object {
msg: "changed",
collection: "users",
id: "sQnaLPj2FvH692rQM",
fields: Object
}
// ??? WHY ????
send Object {
msg: "unsub",
id: "EPgQwMiDggM7wafCN"
}
receive Object {
msg: "removed",
collection: "chatMessages",
id: "G6tv76ZSJYXmnsrAY"
}
receive Object {
msg: "nosub",
id: "EPgQwMiDggM7wafCN"
}
By the way, data is not removed from mongo. If I refresh the page, it chat messages and everything else appear again.
Any help would be appreciated.

Finally I found out the cause of the problem. In my main.html I had something like this:
<div ng-if="$root.loggingIn" class="loading-screen"></div>
<myapp ng-if="!$root.loggingIn"></myapp>
This was made to prevent component's code execution before current user's data is available. I removed ng-if="!$root.loggingIn" from myapp directive and the problem disappeared. I can only guess why it caused such a strange behaviour. Now I use this.autorun() in components to wait for user data.

Related

How to find out when azure snapshot is finished creating

I'm taking a snapshot of a disk on azure. I'm using the Node SDK. When I issue the command to take a snapshot, within a few seconds I get the response back. I'll paste the output below.
The thing is, the provisioning state always shows Succeeded even though the snapshot is obviously not finished being created yet. And it does not yet show in the dashboard.
If I use the snapshot.list the method, it also says Succeeded for this snapshot.
How can I query to find out when the snapshot is actually finished being created?
{ id:
'/subscriptions/1a6c4c11-6729-48fb-8e76-06c6281bb6f1/resourceGroups/RGOUP1/providers/Microsoft.Compute/snapshots/snapCostTest',
name: 'snapCostTest',
type: 'Microsoft.Compute/snapshots',
location: 'westus',
sku: { name: 'Standard_LRS', tier: 'Standard' },
timeCreated: 2019-08-16T00:51:04.099Z,
osType: 'Windows',
hyperVGeneration: 'V1',
creationData:
{ createOption: 'Copy',
sourceResourceId:
'/subscriptions/1a6c4c11-6729-48fb-8e76-06c6281bb6f1/resourceGroups/RGOUP1/providers/Microsoft.Compute/disks/vm1_OsDisk_1_502b5534fe4b4f288d19e127c457d652' },
diskSizeGB: 127,
provisioningState: 'Succeeded' }
I would have thought the provisioningState would show something like Creating while the snapshot is being created.
You can use the the rest API below to get detailed information of your disks :
GET https://management.azure.com/<YOUR DISK ID>?api-version=2018-06-01
Only properties.provisioningState in response value turned "Succeeded" , the disk will shows up on portal dashboard.

Write an object containing an array of objects to a mongo database in Meteor

In my user collection, I have an object that contains an array of contacts.
The object definition is below.
How can this entire object, with the full array of contacts, be written to the user database in Meteor from the server, ideally in a single command?
I have spent considerable time reading the mongo docs and meteor docs, but can't get this to work.
I have also tried a large number of different commands and approaches using both the whole object and iterating through the component parts to try to achieve this, unsuccessfully. Here is an (unsuccessful) example that attempts to write the entire contacts object using $set:
Meteor.users.update({ _id: this.userId }, {$set: { 'Contacts': contacts}});
Thank you.
Object definition (this is a field within the user collection):
"Contacts" : {
"contactInfo" : [
{
"phoneMobile" : "1234567890",
"lastName" : "Johnny"
"firstName" : "Appleseed"
}
]
}
This update should absolutely work. What I suspect is happening is that you're not publishing the Contacts data back to the client because Meteor doesn't publish every key in the current user document automatically. So your update is working and saving data to mongo but you're not seeing it back on the client. You can check this by doing meteor mongo on the command line then inspecting the user document in question.
Try:
server:
Meteor.publish('me',function(){
if (this.userId) return Meteor.users.find(this.userId, { fields: { profile: 1, Contacts: 1 }});
this.ready();
});
client:
Meteor.subscribe('me');
The command above is correct. The issue is schema verification. Simple Schema was defeating the ability to write to the database while running 'in the background'. It doesn't produce an error, it just fails to produce the expected outcome.

What is the correct way to listen to nested changes using Firebase?

Background:
I'm trying to send SMS messages via the browser using Firebase, Twilio, and Node.js. My current data structure in Firebase looks like this:
{ messages :
{ +15553485 :
{ FB-GENERATED-KEY-1 :
{ body: "hello world"
timestamp: 1461758765472 }
},
{ FB-GENERATED-KEY-3 :
{ body: "I love dogs"
timestamp: 1461758765475 }
}
}
},
{ +15550000 :
{ FB-GENERATED-KEY-2 :
{ body: "goodbye world"
timestamp: 1461758765473 }
},
{ FB-GENERATED-KEY-4 :
{ body: "I love cats"
timestamp: 1461758765476 }
}
}
}
}
When a message is added to Firebase via the frontend the backend needs to get notified in order to send an SMS via Twilio. When the backend gets a reply from the phone (via Twilio), it adds it to Firebase.
Problems:
When I listen for changes to a thread I receive all messages sent/recieved for that phone number. Obviously the backend doesn't want to send all the messages again, so I'm only interested in the most recent message added to the thread.
Also I can't seem to easily get the phone number (the key) that has messages underneath it.
What I've tried:
ref.child('messages').on('child_added', ...) — this works for new phone numbers that are added at /messages, however Firebase doesn't send through the new phone number (key), only everything from FB-GENERATED-KEY-2 down.
ref.child('messages').on('child_changed', ...) — this returns all of the messages in a thread, not only the new ones. I can sort on the server and find the most recent message, but that seems like it'll get heavy quite quickly – what if you've sent thousands of messages?
Storing messages at the root level (aka. flattening the tree) and storing the number as an attribute instead could work, but I'm going to need to use the phone number as a sort of index to connect with other data later (like a foreign key).
Questions:
How can I only get the most recent message when listening to activity on the parent /messages and not a particular phone number?
How can I get the key (phone number) when using a child_ event?
Does this data structure make sense?
You can get the Firebase key by calling key() on the snapshot returned by your child_added listener.
Then you can add another nested listener like this:
ref.child('messages').on('child_added', function (snapshot) {
var phone = snapshot.key();
ref.child('messages').child(phone).on('child_added', function (message) {
//send SMS
}, function (error) {
});
}, function (error) {
});
The Firebase API allows you to listen for changes in value or for operations on children. It does not have a way to listen for changes in grandchildren.
In NoSQL databases you often need to model the data for the way your application uses it. If I look at your specific use-case:
When a message is added to Firebase via the frontend the backend needs to get notified in order to send an SMS via Twilio.
I see a queue here:
smsQueue: {
pushId1: {
number: "+15553485",
body: "hello world",
timestamp: 1461758765472
},
pushId2: {
number: "+15550000",
body: "goodbye world",
timestamp: 1461758765473
},
pushId3: {
number: "+15553485",
body: "I love dogs",
timestamp: 1461758765475
},
pushId4: {
number: "+15550000",
body: "I love cats",
timestamp: 1461758765476
}
}
With this structure your back-end (which hopefully uses firebase-queue) can take each task from the queue, call twilio and delete the item from the queue.

Emberjs Deep Model Associations not available in templates

I'm new to Emberjs, and I'm trying to get my head around how to get data out of my model.
Here's the data structure as its being returned from my server
candidate: {
image: [image],
user: {
name: [User Name]
},
agent: {
phone: [phone]
team: {
name: [Team Name]
}
user: {
name: [User Name]
}
}
}
I cant get ember to recognize any associations more than one level deep.
heres my candidate controller
App.CandidateController = Ember.ObjectController.extend({
location: function() {
var address = this.get('address');
var city = this.get('city');
var state = this.get('state');
var zip = this.get('zip');
return address + ' ' + city + ' ' + state + ', ' + zip;
}.property('address', 'city', 'state', 'zip')
});
App.CandidateSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
agent: {embedded: 'always'},
user: {embedded: 'always'}
}
});
This allows me to get one level deep, but I need two or three levels of association.
Is there a different way to go about it?
I thought organizing everything on the server the way I want it displayed, and just returning the data as its supposed to be rendered to ember, but I have a feeling I'll run into problems when trying to update the models.
Any help is appreciated.
/****** UPDATE *******/
I have refactored my code and I am now returning data from the serializer like this:
{
candidate: {
// relevant fields
},
agent: {
//relevant fields
},
team: {
// relevant fields
}
user: [
{ // candidate user fields },
{ // agent user fields }
]
};
However, data is still not available in my template. In the Ember chrome extension, in the data tab, I get
candidate: (1)
agent: (0)
team: (0)
user (2)
I can see candidate and user data, but not agent or team data. In my candidate model, I have:
App.Candidate = DS.Model.extend({
// other fields
user_id: DS.attr('number'),
agent_id: DS.attr('number'),
user: DS.belongsTo('user'),
agent: DS.belongsTo('agent')
});
It doesn't seem like the belongsTo association actually does anything.
So the first issue is that I'm not getting the correct data, the second issue, and the one that makes me think I am going about this incorrectly, is that I have two users information that I need to display in the template. The first is user information associated with the candidate, and the second is user information that is associated with the agent. Both data need to appear in the same template. Since there is no hierarchy to the data, how would the template know which user info to display in each location?
Again, I think Im thinking about this whole thing incorrectly.
Thanks for your help.
Ember data expects models in a JSON response to be flat, and it's the job of the Serializer to transform your server response into that format. Associations usually are done by ids. The second level is not working because Ember needs to turn each level into an Ember.Object in order to observe property changes.
It might help to look over the JSON conventions portion of the guides. You can also plug your models into the ember data model maker and see what your responses should look like. Finally, make sure you're using the ember-inspector Chrome extension. When I am debugging ember-data related issues, it's usually easiest to just stop after the model hook returns, look in the inspector's store tab, and examine what data has been loaded.

Ember.js: Save record to Ember.Data, wait for response before displaying

I'm building an app which allows users to post to Twitter. When they click the submit button we close the posting form. We create a Message object which is saved to the data store and sent to the server. The server creates a Post object, then submits a request to Twitter. The server then updates the Post object, replies back to the UI with the updated information.
That part is already working. But I need to know if it's NOT working so that I can alert the user that their message did not go through and keep the posting form open. Here's some pertinent information about my app.
Social.Message = DS.Model.extend({
text: DS.attr("string"),
created: DS.attr("date"),
isPending: DS.attr("boolean"),
posts: DS.hasMany("Social.Post")
});
Social.Post = DS.Model.extend({
text: DS.attr("string"),
status: DS.attr("string"),
created: DS.attr("date"),
message: DS.belongsTo("Social.Message"),
msgStatus: function() {
return ((this.get('status') === 'S') ? true : false);
}.property('status')
});
The lifecycle of a post (status) goes from P (pending) to Q (queued) to S (sent), E (error) is also a possibility, and the status that I'm really looking for. Here's the saveMessage method:
saveMessage: function(text){
var acct = Social.Account.find(this.get("id")),
msg = Social.store.createRecord(
Social.Message,
{
text: text,
created: new Date()
}
);
acct.get("messages").addObject(msg);
Social.store.commit();
Ember.run.later(this, function() {
msg.get('posts').forEach(function(p){
p.reload();
});
}, 1000);
}
You can see that I pause for a second to let the server process, then attempt to reload the Post object with the response from Twitter. Those last few lines are where I think this new code would go, but I'm not sure how to listen to something that might not come back. I'd rather not "wait" for a second, instead it would be nice if the message could just update. Not sure how to accomplish that though.
Thoughts?
You need to run your code as a callback after the record is created. This is how:
msg.one('didCreate', function() {
// transition to new route showing data just created
});
Social.store.commit();
This will add a one time call on the record for when it is created. There are also 'didUpdate' and 'didDelete' hooks as well. You need to add these callbacks before the create is called (obviously).
I'm not sure how to handle the error condition as I haven't looked into that yet.
Edit: this is actually broken, per https://github.com/emberjs/data/issues/405, so waiting may be the only option currently.
It sounds like you don't want the two-way data binding here and you might benefit from one-way instead. Here is a great full length blog post that explains it a bit more in depth
http://www.solitr.com/blog/2012/06/ember-input-field-with-save-button/

Categories