Advice in Datadesign for nosql (firebase) - firebase

I'm new to the noSQL-Thing (I use firebase Realtime-Database for starters) and I'm writing a react-js app to manage Meetings and their Agenda Points.
The meeting has some attributes(name, planed duration, Start time, ... ) and the Agendaitems as well (name, planed duration, ... ).
So, my first intuition was to make a class Meeting with a Map of AgendaItems - but the Map doesn't get save in the firebase.
Then I tried a simple array - this works but I read "Arrays are bad in firebase"
So, whats the best strategy here? (I know that is probably a very Basic question)
And, would you put more "advanced" functions in the same Class? - e.g.: "nextAgendaItem", "addAgentaItem" to capsulate these implementation
or would you build a own "HandlerClass" witch has a Meeting as member

Related

How to create an alert to notify an user when some amount % of threshold reached DailyAsyncApex Executions

On 2 occasions in the past month, we have managed to hit our daily limit on asynchronous apex executions. Salesforce temporarily increased our limit to 425000 but it will be scaled down to 250000 in a week's time. Once we reach the limit, a lot of the SF functions will fail and this has tremendously impacted both internal staff and external customers.
So to prevent this from happening in the future, we need to create some kind of alert in Salesforce to monitor our daily asynchronous apex method executions. Our maximum daily limit is 250000. The alert will need to create a P3 helpdesk ticket and notify couple of users say USER A and USER B once it reaches 70% threshold.
Kindly advise what is possible to achieve the same
Thanks & Regards,
Harjeet
There's a promising Limits method but it doesn't seem to work currently ("reserved for future use"): System.debug(Limits.getAsyncCalls() + ' / ' + Limits.getLimitAsyncCalls());
There's an idea you can upvote: https://success.salesforce.com/ideaView?id=0873A0000003VIFQA2 ;)
You could query SELECT COUNT() FROM AsyncApexJob WHERE ... but that sounds like a bad idea ;)
I think your best course of action is to use SF REST API. There's a "limits" resource you can fetch. You could do it from SF itself (bad idea because if you'd schedule it to run every hour then well, of course it will contribute to the limit consumption too ;)) or from some external app that'd connect to your SF...
https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_limits.htm
You can quickly try it out for example in workbench.developerforce.com before you decide you do want to deep dive into coding it.
Of course if you have control over your batch jobs, queuable, schedulable & #future calls you could implement some rough counter of executions in a helper object for example... won't help you much if most of the jobs are coming from managed packages though...
Got 1 more idea but it's pretty hardcore - you should be able to make a REST API call from javascript. so you could create a simple VF page (even without any apex controller), put JS callout on it, have it check every 5 mins and do something if threshold is hit... But that means IT person would have to have this page open all the time (perhaps as a home page component)... Messy :)
I was having the exact same issue so I created a simple JsForce script in NodeJS to monitor the call to the /limits endpoint.
You can connect a Free Monitoring service like UpTimerobot.com or PingDom.com and get an email when you find the Word "Warning" >50% or "Error" > 80%.
async function getSfLimits() {
try {
//Let's login into salesforce
const login = await conn.login(SF_USERNAME, SF_PASSWORD+SF_SECURITY_TOKEN);
//Call the API
const sfLimits = await conn.requestGet('/services/data/v51.0/limits');
return sfLimits;
} catch(err) {
console.log(err);
}
}
https://github.com/carlosdevia/salesforcelimits

Meteor realtime game - match two players according to their score?

I want to build a realtime quiz game which randomly matches two players (according to their winning rate if they are logged in). I've read through the book Discover Meteor and have a basic understanding of the framework, but I just have no idea of how to implement the matching part. Anyone know how to do that?
if you want to match users who have scores close to each other, you can do something like this : mongodb - Find document with closest integer value
The Meteor code for those Mongo queries is very similar, but there are some subtle differences that are kind of tricky. In Meteor, it would look something like this :
SP // "selected player" = the User you want to match someone up with
var score = SP.score; // selected player's score
var queryLow = {score: {$lte:score},_id:{$ne:SP._id}};
var queryHigh = {score:{$gte:score},_id:{$ne:SP._id}};
// "L" is the player with the closest lower score
var L=Players.findOne(queryLow,{sort:{score:-1},limit:1});
// "H" is the player with the closest higher score
var H=Players.findOne(queryHigh,{sort:{score:1},limit:1});
so, now you have references to the players with scores right above and right below the 'selected player'. In terms of making it random, perhaps start with a simple algorithm like "match me with the next available player who's score is closest" , then if it's too predictable and boring you can throw some randomness into the algorithm.
you can view the above Meteor code working live here http://meteorpad.com/pad/4umMP4iY8AkB9ct2d/ClosestScore
and you can Fork it and mess about with the queries to see how it works.
good luck! Meteor is great, I really like it.
If you add the package peppelg:random-opponent-matcher to your application, you can match together opponents like this:
On the server, you need to have an instance of RandomOpponentMatcher like this:
new RandomOpponentMatcher('my-matcher', {name: 'fifo'}, function(user1, user2){
// Create the match/game they should play.
})
The function you pass to RandomOpponentMatcher will get called when two users been matched to play against each other. In it, you'll probably want to create the match the users should play against each other (this package does only match opponents together, it does not contain any functionality for playing games/matches).
On the client, you need to create an instance of RandomOpponentMatcher as well, but you only pass the name to it (the same name as you used on the server):
myMatcher = new RandomOpponentMatcher('my-matcher')
Then when the users is logged in and which to be matched with a random opponent, all you need to do is to call the add method. For example:
<template name="myTemplate">
<button class="clickMatchesWithOpponent">Match me with someone!</button>
</template>
Template.myTemplate.events({
'click .clickMatchesWithOpponent': function(event, template){
myMatcher.add()
}
})
When two different logged in users has clicked on the button, the function you passed to RandomOpponentMatcher on the server will get called.
One implementation might be as follows:
A user somehow triggers a 'looking for game' event that sets an attribute on user.profile.lookingForGame to true. The event then makes a call to a server side Meteor method which queries for all other online users looking for games.
From there you it really depends on how you want to handle users once they 'match'.
To determine all online users, try using the User Status package:
https://github.com/mizzao/meteor-user-status
Once added, any online user will have an attribute in the profile object of 'online'. You can use this to query for all online users.

firebase more complex validation

I'm creating an angular app with firebase back end as an API.
People will be able to book appointments on a calendar but 2 persons CANNOT share the same hour slot. Furthermore, since appointments can start every half and hour, checking becomes a bit more complex.
Can I make firebase perform some more complex validation like that? It pretty much covers everything else I need and I'd hate to create something custom, only because of that feature!
Thanks!
If I am correct, you said you don't want to do the checking client-side. Sounds good. Here's what I would do:
When storing the appointments, I would name them based on their times. Client-side code:
var dataRef = new Firebase('https://example.firebaseio.com/');
dataRef.child('2014-6-9-0500').set('name'); // 5:00 6/9/2014 converted to a string
So the appointments will all be named based on their time, and their values will be equal to the name of the person being scheduled at that time. This will make it impossible for two people to be scheduled at the same time (because in Firebase, there cannot be two children with the same name).
In your security tab, check that the data doesn't already exist (to prevent over-writing existing appointments). Then, for the validate, you could check the appointment time and make sure it ends with either "00" or "30", and is 12 digits long. The rules would look something like this:
"rules": {
".read": true,
"$time": {
".write": "!data.exists()",
".validate": "$time.endsWith('00') || $time.endsWith('30')"
}
}
Although it's possible for a nonvalid time to be accepted (such as "0000-0-0-0030" or even "qt00"), a valid appointment which is submitted will not be scheduled at the same time as another appointment, and the appointments will be at times ending at ":00" or ":30" (half-hour intervals).
The only problem is if a person has an hour-long appointment starting at noon. You would have to schedule multiple appointments: one at 12:00, and another at 12:30. That could get a little annoying, but I don't know of any other way to do it.
In my understanding, it is possible with Firebase. However, Firebase does not have the dynamic querying capabilities like Mongo does. I believe you have to take a pretty primitive approach to solving this issue by doing something like:
db.child('calendar').once('value', function(snapshot){
var hours = snapshot.val();
// for each hour
// do validation here
})

Most efficient method of pulling in weather data for multiple locations

I'm working on a meteor mobile app that displays information about local places of interest and one of the things that I want to show is the weather in each location. I've currently got my locations stored with latlng coordinates and they're searchable by radius. I'd like to use the openweathermap api to pull in some useful 'current conditions' information so that when a user looks at an entry they can see basic weather data. Ideally I'd like to limit the number of outgoing requests to keep the pages snappy (and API requests down)
I'm wondering if I can create a server collection of weather data that I update regularly, server-side (hourly?) that my clients then query (perhaps using a mongo $near lookup?) - that way all of my data is being handled within meteor, rather than each client going out to grab the latest data from the API. I don't want to have to iterate through all of the locations in my list and do a separate call out to the api for each as I have approx. 400 locations(!). I'm afraid I'm new to API requests (and meteor itself) so apologies if this is a poorly phrased question.
I'm not entirely sure if this is doable, or if it's even the best approach - any advice (and links to any useful code snippets!) would be greatly appreciated!
EDIT / UPDATE!
OK I haven't managed to get this working yet but I some more useful details on the data!
If I make a request to the openweather API I can get data back for all of their locations (which I would like to add/update to a collection). I could then do regular lookup, instead of making a client request straight out to them every time a user looks at a location. The JSON data looks like this:
{
"message":"accurate",
"cod":"200",
"count":50,
"list":[
{
"id":2643076,
"name":"Marazion",
"coord":{
"lon":-5.47505,
"lat":50.125561
},
"main":{
"temp":292.15,
"pressure":1016,
"humidity":68,
"temp_min":292.15,
"temp_max":292.15
},
"dt":1403707800,
"wind":{
"speed":8.7,
"deg":110,
"gust":13.9
},
"sys":{
"country":""
},
"clouds":{
"all":75
},
"weather":[
{
"id":721,
"main":"Haze",
"description":"haze",
"icon":"50d"
}
]
}, ...
Ideally I'd like to build my own local 'weather' collection that I can search using mongo's $near (to keep outbound requests down, and speed up), but I don't know if this will be possible because the format that the data comes back in - I think I'd need to structure my location data like this in order to use a geo search:
"location": {
"type": "Point",
"coordinates": [-5.47505,50.125561]
}
My questions are:
How can I build that collection (I've seen this - could I do something similar and update existing entries in the collection on a regular basis?)
Does it just need to live on the server, or client too?
Do I need to manipulate the data in order to get a geo search to work?
Is this even the right way to approach it??
EDIT/UPDATE2
Is this question too long/much? It feels like it. Maybe I should split it out.
Yes easily possible. Because your question is so large I'll give you a high level explanation of what I think you need to do.
You need to create a collection where you're gonna save the weather data in.
A request worker that requests new data and updates the collection on a set interval. Use something like cron-tick for scheduling the interval.
Requesting data should only happen server side and I can recommend the request npm package for that.
Meteor.publish the weather collection and have the client subscribe to that, with optionally a filter for it's location.
You should now be getting the weather data on your client and should be able to get freaky with it.

Prolog: Recursion and splitting lists

I'm trying to write a game in which the program reads through a database, grabs attributes and asks the player if the Movie that the player is thinking of will have that attribute. The user will answer either yes or no and if yes, the game will ask about the next attribute until either the user has said yes to every attribute, at that point the program will output the name of the movie. Or if the user says no, the game will then move along to the next movie in the database and start asking about those attributes.
The game ends when either it finds a movie with all the attributes or there are no more movies in the database in which the program could ask about.
Here is the database file.
object_properties(crocodile_dundee,[comedy,australian,paul_hogan_movie]).
object_properties(flipper,[action_movie,australian, paul_hogan_movie,
-comedy]).
object_properties(jackass,[comedy,-australian]).
object_properties(the_godfather,[drama,crime,-character_batman]).
object_properties(the_dark_knight,[drama,crime,character_batman]).
object_properties(the_living_planet, [documentary,director_attenborough]).
object_properties(the_code, [documentary,nerds_love_it]).
object_properties(the_russian_revolution, [documentary,about_history]).
Here is my game file.
go():-
guess_object(0,[]).
guess_object(Obj,[A|As]) :-
object_categories(Obj,A).
guess_object(1).
guess_object(2).
guess_object(3).
guess_object(4).
guess_object(5). %how do i do this specifically for the current Obj attributes?
guess(X) :- guess_object(_, X),
writeln('Does your object have the attribute '(X)'?'),
read(Input), Input=('yes') -> assert(object(X)) ; retractall(X), guess(X).
writeln('I guess that the film is: 'guess_object(Obj,_).
The main questions I have:
How do I split the object attributes in to a list like I'm trying to do on guess_object(1) through to guess_object(5) depending on whether the object has 2 attributes or 4 attributes, etc.
How do I make my guess(A) predicate recursive so once the user says no it will then go to the next object in the database file?
I'm not too great at prolog but any advice or pointers would be greatly appreciated, even if it's just pointing out a stupid mistake I may have made. I will also answer any questions anyone has to the best of my ability.

Resources