Appwrap: Identifying a Stale Room when building a Chat Client - javascript

I am extending this chat client built using AppWarp Client API and App42 Backend.
After appropriate initializations and setting listeners I am successfully able to fetch all available rooms using _warpclient.getAllRooms(); and its listener:
function onGetAllRoomsDone(rooms) {
console.log(rooms);
for(var i=0; i<rooms.getRoomIds().length; ++i) {
_warpclient.getLiveRoomInfo(rooms.getRoomIds()[i]);
}
}
Problem:
However, rooms.getRoomIds() returns dynamic rooms that are stale (dead / destroyed see: dynamic rooms here). Is there a way to identify these stale rooms?
Attempts:
I have extensively searched their API reference but haven't
found any information on how to achive this.
I also explored the room objects received in the callbacks onGetLiveRoomInfoDone and onGetAllRoomsDone but it doesn't contain anything relevant.
Their App42 Management Console doesn't provide a list of these rooms or their properties.

If a room has been destroyed/dead, it won't appear in getRoomIds(). It might be the room is not dead but empty. Try joining any such room, you will be able to join it. If It was dead, your join room request will fail.
A rare case can be, when you called getAllRooms(), there was someone in room and hence you got it in the result, but the before you can send the join request, it got empty and destroyed.

Related

Clean Architecture in NodeJS, how do useCases interact with each other?

I am trying to implement the Clean Architecture by Bob Martin in my project and I have a question.
How do use-cases interact with each other?
For example:
I have a Department entity and Employee entity.
Department entity has a peopleCount field
Whenever a new Emplyoee is created it is also assigned to a Department, which means that peopleCount must increase by 1.
So how should that interaction between say addEmployee.js and editDepartment.js use-cases be?
Do I const editDepartment = require("../departments"); within my addEmployee.js and use it within addEmployee.js?
Do I inject it as a dependency and then use it?
Do I create a separate useCase increasePeopleCountInDepartmentById.js and require/inject that one? So that its something with a specific purpose and not the "general" editing.
How do use-cases interact with each other?
A use-case is a scenario in which a system receives an external request (such as user input) and, following a list of actions, responds to it (Wikipedia). Therefore, use-cases by definition cannot interact with each other. Moreover, they have not interest to interact with each other.
A use-case, be it addEmployee or editDepartment (depending on your system design), should orchestrate participating domain entities (employee and department). Again, mixing use-cases is irrelevant.
Here's how you can implement addEmployee:
// TODO: start database transaction
const newEmployee = employeeFactory.create(id, name, age, targetDepartmentId);
const department = departmentRepository.get(targetDepartmentId);
department.peopleCount = department.peopleCount + 1;
departmentRepository.save(department);
employeeRepository.add(newEmployee);
// TODO: commit transaction
Do I inject it as a dependency and then use it?
As can be inferred from my example, three objects are to be injected into use-case: employeeFactory, departmentRepository, employeeRepository.

What is best rest api design when you have condition call?

I have a condition call. To check condition you need to call other endopint. What is better api design?
e.g
if(fetch('api/is-data-valid')){
const data = fetch('api/get-profile-data');
// do something with data
}
or
const data = fetch('api/get-profile-if-data-valid');
if(data.isDataValid) {
// do something with data
}
If the client can't work out whether the data is valid, the API should respond accordingly, without an extra step.
Instead of checking api/is-data-valid to get api/get-profile-data, do it in one request, which hides the implementation suggested by api/get-profile-if-data-valid
You can only get profile-data if the data is valid so let the API work it out.
fetch('api/get-profile-data'); // returns profile data or 404
and let the client concentrate on displaying an error saying the data is invalid because the corresponding profile doesn't exist.
The answer depends on a few things. In general it's best to keep the number of api calls to a minimum so doing one call instead of two is preferable. However if there are cases that someone would want to check if data is valid without getting the profile, then having the is-data-valid api is important.
My advice would be to have both api's but allow someone to call get-profile-data when it's invalid and handle that case in a well defined way. This would allow the work to be done with a single call, but still allow other use cases where checking the data validity is useful on its own.

Firebase trigger on all collection items while only one has been updated

Every time I do an update with the same object(s3) with same values and properties, Firebase trigger the event 'child_added' even if there's nothing to add or update.
I made some test by modifying on the firebase console some values in subcollection of the main object and noticed that it returns a snapshot with the first element correct and then all the other elements of the collections as 'ADDED' elements. This is not true because the collections didn't change except the one on which I performed an action.
I just need that when I send the same identical object that is stored on the db, firebase will recognize smartly that no action is requested and no trigger need to be activated.
var studentiRef = ref.child('studenti/' + s3.matricola);
studentiRef.update(JSON.parse(JSON.stringify(s3)));
studentiRef.on("child_changed", function(userSnapshot) {
var tasseRef = userSnapshot.ref.child('tasse');
tasseRef.on('child_added', function(itemSnapshot, prevKey){
console.log('ADDED ON');
console.log(itemSnapshot.key)
})
});
studentiRef.on("child_changed", function(userSnapshot) {
userSnapshot.ref.child('tasse').on('child_removed', function(itemSnapshot, prevKey){
console.log('REMOVED ON');
console.log(itemSnapshot.key)
})
});
studentiRef.on("child_changed", function(userSnapshot) {
userSnapshot.ref.child('tasse').on('child_changed', function(itemSnapshot, prevKey){
console.log('CHANGED ON');
console.log(itemSnapshot.key)
})
});
UPDATE:
Before posting update I made some experiments with no successful results.
Here the pics of the console, the database and the code.
Going nuts on this.
Here three screenshot: 1 firebase data 2 snippet 3 console log
UPDATE II:
scenario
behaviours on modifying value in firebase
SOLVED:
By getting inspired from the github firebase examples, I found out a common mistake in using firebase: i was not flatting the data.
To continue using my data structure (a root object within a list of objects), the solution was to trigger an update of every single object (pseudocode: ref.update(root/childobject) n-times instead of ref.update(root).
If someone else ran into this problem, I will explain better.
Always, FLAT YOUR DATA! (using firebase)
Most likely these events come directly from the client SDK, which doesn't detect if there was an actual change. The database server does perform such a check, and will only send out changes to other clients if there was an actual change.
Update:
The Firebase client + server behave in the following way when you're calling telling it to update a node to its current value.
The client fires the local event(s) to reflect the update. So child_changed will fire.
The client send the update to the server. This is needed since the client and server may be (slightly) out of sync, and the server is the single-source-of-truth.
The server compares the update with the current value of the node. If it is the same, the process stops here.
If the updated value is different from the current value and passes validation/permission checks, the data is committed to disk and broadcast to any active listeners.
If the updates value is different, but rejected by the validation/permission checks, the servers sends a rejection message to the original client, which then fires another child_changed event to revert the local change.

Whats a better way to have unique user rooms

The logic is click user, checks for existing rooms. If there is, go to existing room. If not, creates new room and goes into it. There will only be a unique room between the user and myself. When I click user for first time, it sets a unique Id for the room. But if i click the name a 2nd time, it routes me to a room with url params as user's Id.
Was wondering whats wrong and if theres a cleaner way. I also cant display the name of the receiver. I used helpers Meteor.users.findOne({ _id: this.receiver }).
roomDetail
//subscription
self.subscribe('room', Router.current().params._id);
//.. room helper
return Rooms.findOne({ _id: Router.current().params._id });
User page to click button
Template.usersShow.events({
'click .user': function(event) {
var receiver = this._id;
if (receiver) {
var res = Rooms.findOne({ 'receiver' : receiver });
if(res){
//..route to the existing room
} else {
//...create new room
In order to ensure that there is only one room between any pair of users you should treat both the "initiator" and the "receiver" equally. Below I describe one way of doing just that.
A room has an id (the built in _id) and the ids of both users:
{
userA: "aaaa",
userB: "bbbb",
// ...
}
When finding a room between "aaaa" and "bbbb", we don't know which is which. We can avoid this problem by imposing the rule that userA has the id that sorts before userB. To make it easy to use this rule, we write a helper function:
function userAAndB(user1, user2) {
if (user1 < user2) return {userA: user1, userB: user2};
else return {userA: user2, userB: user1};
}
Now if we want to find the room for users x and y, we can find it like this:
var theRoom = Rooms.findOne(userAAndB(x, y));
The helper can also be used as a starting point for creating a new room.
In order to find all rooms that a user is in, we can use an $or operator:
var allRoomsWithX = Rooms.find({$or: [{userA: x}, {userB: x}]});
Using this design, there are a couple of ways that you can implement your routes and buttons:
Put the other user's id in the route, like allRooms/:otherUser. The router, template and publication can use userAAndB(userId, otherUser) to find the room they need.
In this case, you need some code that creates the room if it doesn't exist. On the server is best, so you could put it in the publish function. This means that the client doesn't need to know the room id, and can simply link to the right route.
Put the room id in the route, like allRooms/:_id. The router, template and publication can use the room's _id.
In this case, you need to find out what the correct room id is for a given pair of users in order to make a link. This is pretty easy using userAAndB(userId, otherUser). You also need to create a new room if one doesn't exist. You could do this when the user clicks on the link.
It might be best to make a Meteor Method to get the room id for a pair of users so that you don't need to send all of the rooms to the client. The method would be something like getRoomId(user1, user2) and it would create a room if needed, then return the id.
Slightly related, because you are asking about nicer ways to structure code, I want to mention Iron Router's waitOn and data features.
You can have Iron Router make subscriptions and fetch data for you, so that you don't need to do it in your templates. This is great if a template can't be sensibly rendered until the main data has loaded, and would probably be good in your roomDetail route. Look for waitOn and data in this section of the Iron Router guide for an example.

Can an object's methods act on itself?

I'm not sure where to put some methods.
Let's say I want to send an email.
Which of the following options should I choose:
email = new Email("title", "adress", "body");
email.send();
or
email = new Email("title", "adress", "body");
Postman.send(email);
Because how can an email send itself? And isn't it better to have a central object that handles all emails because then he can regulate things like sending all emails at a specific time, sort mails, remove mails etc.
Also if I want to delete an user, how should I do:
user.delete();
or
administrator.delete(user);
Please share your thoughts about how to know where to put the methods.
I disagree with Arseny. An email can send itself, and that's exactly where the code should live. That's what methods are: actions that can be performed on the object.
However, note that your approaches are not mutually incompatible. An email's send action could easily just contain the code to add itself to the Postman's send queue, and if you do want to regulate the actions, that might be a good idea. But that's no reason not to have a send method for the email class.
All sensible methods that act on emails should be in the email class, for the convenience of users of your class. But email objects should not contain any fields except those related to the content of the email itself (single responsibility principle).
Therefore, I'd suggest this:
class Email
def email(postman)
postman.send(self)
end
end
In statically typed languages, the type of the postman argument should definitely be an interface.
Use the second method to have a class manager handle the objects (emails or users). This follows the single-responsibility-principle.
In Ruby I'd do this:
email = Email.deliver(recipient, subject, message)
The correspoding class would look something like this:
class Email
def self.deliver(recipient, subject, message)
# Do stuff to send mail
end
end
This is clean and easy to use.
On the delete issue: Delete the object you want to delete. So #user.delete would be best. If you want to register the administrator who deleted the user: #user.delete_by(#admin)
I agree with Daniel.
Following your first example, a lot of common widgets would also have a "collections" manager like you mentioned but they don't necessarily. A Tabs widget can show/hide one of its own tabs, without necessarily specifying a new Tab class for each individual one.
I believe functionality should be encapsulated. The example of deleting a user however, is a slightly different case. Having a delete method on the User class could do stuff like clear its own internal variables, settings, etc, but it won't delete the reference to itself. I find that delete methods are better suited for collection-based classes. I wouldn't per se put the delete method on a admin class but rather on a Users "collection" class.
function Users(){
var users = [];
this.add = function(user){
// add user code
users.push(new User(user));
}
this.remove = function(user){
// remove user code and remove it from array
}
}
I don't quite see how an object can fully add/remove itself so it makes sense to me to have that functionality at the collections level. Besides that though, I would say it should be encapsulated within the class it's meant for.

Categories