Firebase Connection Manager Should Return Only One Result

Firebase: How to update multiple nodes transactionally? Swift 3

In the Firebase documentation in the section Enable Offline Capabilities it is specified that:

Transactions are not persisted across app restarts

Even with persistence enabled, transactions are not persisted across
app restarts.

So you cannot rely on transactions done offline being
committed to your Firebase Realtime Database.

Therefore:

1. there is no way to use firebase transactions at client side to update a value at two or more paths.

2. using a completion callback to perform the second write is not viable since the client could restart the app before a response is received in the completion handler from the firebase server, thus leaving the database in inconsistent state.

I assume that my only option to update data transactionally at the first path and further update the second path with that data that was already written at the first path in Firebase Database, would be to use Conditional Requests over REST as specified in the Firebase Documentation.

This would achieve the same functionality provided by Firebase framework for IOS clients.

    1. The client will make a request via Alamofire to my server (I will use Vapor framework so as to leverage the Swift language), once the request is received at the Vapor server, a GET request will be sent to the Firebase Database server root/users/bookings/4875383 in which I will request an ETAG_VALUE

What is ETAG Value?: ( a unique identifier which will be different every time data changes at the path where GET Request is made. Namely if another user writes to the same path before my write request the resource succeeds, my write operation will be rejected since the ETAG value at the path will have already been modified by the other user's write operation. This would enable users to write data transactionally to a path)


    1. a response is received from the Firebase Server containing a an ETAG_VALUE.

    1. make a PUT request to the Firebase Server and in the header specify the ETag: [ETAG_VALUE] received from the previous GET request. If the ETAG value posted to the server matches the value at the Firebase Server, the write will succeed. If the location no longer matches the ETag, which might occur if another user wrote a new value to the database, the request fails without writing to the location. The return response includes the new value and ETag.

    1. Furthermore, now we can update the value at root/Cleaners/bookings/4875383 to reflect the job that was claimed by a cleaner.

How to merge results of two queries in Firebase Realtime Database

To get the combined result of two separate Firebase Realtime Database queries, I recommend you to use Tasks.whenAllSuccess() method. You can achieve this, using the following lines of code:

query = MainNewsDb.orderByChild("department").equalTo("Management").limitToLast((int)limit);
query1 = NewsListDb1.orderByChild("department").equalTo("all").limitToLast((int)limit);

Task firstTask = query.get();
Task secondTask = query1.get();

Task combinedTask = Tasks.whenAllSuccess(firstTask, secondTask).addOnSuccessListener(new OnSuccessListener<List<Object>>() {
@Override
public void onSuccess(List<Object> list) {
//Do what you need to do with your list
}
});

As you can see, when overriding the "onSuccess()" method the result is a list of objects. As soon as you have it, simply map each object from the list into an object of the desired type.

update location to the firebase database every 15 minutes only if the location has been changed? Android

I found a solution for this. You can save a longitude and latitude in Shared Preferences and check whether user has gone more than 100m. If it is true you can update the server and you can update Shared Preferences also.

    SharedPreferences prefs = getSharedPreferences("code", MODE_PRIVATE);
count = prefs.getInt("location_history",0);

storedLat = prefs.getFloat("storedLat", 0);
storedLon = prefs.getFloat("storedLon", 0);
storedAccu = prefs.getFloat("storedAccu", 0);

float distance = distanceBetweenEarthCoordinates(storedLat, storedLon, (float) location.getLatitude(), (float) location.getLongitude());
if (distance > 100) {
Log.d("TAG", "onLocationResult: New Point" + count + "Distance: " + distance);
storedLat = (float) location.getLatitude();
storedLon = (float) location.getLongitude();
SharedPreferences.Editor editor = getSharedPreferences("uinfo", MODE_PRIVATE).edit();
editor.putFloat("storedLat", storedLat);
editor.putFloat("storedLon", storedLon);
count++;
editor.putInt("location_history", count);
editor.apply();
}

distanceBetweenEarthCoordinates method

public static float degreesToRadians(float degrees) {
return (float) (degrees * Math.PI / 180);
}

public static float distanceBetweenEarthCoordinates(float lat1, float lon1, float lat2, float lon2) {
float earthRadiusKm = 6371;

float dLat = degreesToRadians(lat2 - lat1);
float dLon = degreesToRadians(lon2 - lon1);

lat1 = degreesToRadians(lat1);
lat2 = degreesToRadians(lat2);

float a = (float) (Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2));
float c = (float) (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)));
return earthRadiusKm * c * 1000;
}

Do SingleValueEvent listeners count towards 'simultaneous connections' in Firebase RealTime DB until explicitly removed?

Listening for a single event is exactly the same as adding a normal listener. The SDK just removes that listener after the first time it's triggered.

Removing the last listener doesn't necessarily "release" the connection immediately. As an optimization, the connection will stick around for a while, then get dropped due to a lack of listeners.

How to get single dataBase reference from Firebase

Since your code that adds a particular Locator struct is called multiple times, check your array to make sure it doesn't already contain the exact same struct before adding it to the array locally.

This will evaluate your array of structs and determine if there is no value for it. But it also assumes that name property of the struct is a unique identifier for each struct, which may not be your case. You can alternatively compare any value within the filter closure that you want to make sure isn't duplictated, i. e. lat and long.

    let locator = Locator(name: "Raunak Trikha", long: fetchLong, lat: fetchLat)
if self.friendLocator.filter({ $0.name == locator.name }).count == 0 {
self.friendLocator.append(locator)
}
self.locateFriend()


Related Topics



Leave a reply



Submit