Partial Realms - Why and When are They Created? - realm

I am using Realm and building a Swift mobile app. I am really struggling to understand why and when Partial realms are created.
Here is my scenario:
a user logs in to the app and is brought to the first view controller.
In the first view controller in view did load, I am executing a query to get the current user, subscribing to the query and adding an observer to let me know when the data is synced:
let currentUserArr = realm.objects(DBUser.self).filter("id == %#", userId)
self.subscription = currentUserArr.subscribe(named: "current user")
self.subscriptionToken = self.subscription.observe(\.state, options: .initial) { state in
switch state {
case .creating:
print("creating")
case .pending:
print("pending")
case .complete:
print("complete")
self.artist = currentUserArr[0]
case .invalidated:
print("invalidated")
case .error(let err):
//seal.reject(err)
print(err)
}
}
This makes sense that if I check Realm Cloud, I have a new partial realm created with path as:
/db/__partial/DyeOy3OR4sNsqMi2OmDQQEzUa8F3/~7f11cf52
However, here is where my confusion starts. I log the user out. I log back in and again the code above executes. My thought would be that Realm would just reuse the partial already created, but instead it creates an entirely new partial.
/db/__partial/DyeOy3OR4sNsqMi2OmDQQEzUa8F3/~8bc7bc49
Is this by design or should I somehow be reusing partials rather than having a new one created every time a query is executed (even if it is executed by the same user)?
I have posted on Realm Forums as well:
https://forums.realm.io/t/realm-platform-realm-path-partial-s/2833

I don't believe I was actually logging the current sync user out. Upon further testing, once I did log out and log back in, the existing partial was re-used. This is a non-issue.

Related

What I misunderstood about the Mediator Pattern?

I'm new here and a beginner architect. I'm helping the company I work to design our new product and since I start it, I read a lot about but is never enough.
I decided to use Mediator Pattern (with Mediatr) to call my application layer.
It's cool and I got how to work with it sometimes, but sometimes I get confused.
For example, when we publish a document on our new product, we uses a RequestHandler to do everything and check all rules it needs, it's fine and works like a charm, but, when I want just a quick data, it looks likes too much for just a simple thing.
As an example, every time the user do any kind of action on my web application, I have to check if he is still logged. We have single login per user, so, if the same user connect anywhere else, the older session expires. We do it by saving on database.
On every action of my app, I go to base and check if the session key is the same, as bellow.
var sessionKey = bibliotecaCookie.Value;
var mediator = controller.GetMediator();
var isUserSessionKeyValidRequest = new IsUserSessionKeyValidRequest()
{
sessionKey = sessionKey
};
var isValidSession = mediator.Send(isUserSessionKeyValidRequest).Result;
if (!isValidSession)
throw new UnauthorizedAccessException();
So, I have a RequestHandler (a Handler and a Request which returns a bool) just to check if the user session is ok.
When the handler catches this request, it goes to database and execute a simple rule which is "Is the passed session the same as the stored session key?".
Is it right? Is it the right approach? Did I understand it right?
Thanks in advance guys

how to update/insert/delete item in akavache list object?

Should I use akavache as a primary local database in my xamarin forms application or a cache database on top of another sqlite database? Because I cant find any example of how to update, insert, delete data in akavache object. For example,
CacheItems= await BlobCache.LocalMachine.GetOrFetchObject<List<Item>>("CacheItems",
async () => await getdatafromAzure(recursive));
I am getting items from azure and store in local machine and these items are editable / deleteable or user can add a new item. How do I do it?
Anything saved to LocalMachine gets persisted physically to the device. So on app or device restart it'll still be there (if the user hasn't removed the app or cleared the data that is)
As far as how to access/save there's lots of good samples here
https://github.com/akavache/Akavache
Insert Object and Get Object are your basic access methods and then there's lots of extension methods like GetOrFetch, GetAndFetch, which are very useful
Here's a quick sample I haven't super tested to give one way to access stuff. It'd probably be better to use some of the extension methods but I figure an example like this is conceptually useful.
BlobCache.LocalMachine.GetObject<Tobject>(someKEy)
.Catch((KeyNotFoundException ke) => Observable.Return<Tobject>(null))
.SelectMany(result =>
{
//object doesn't exist in cache so create a new one
if (result == null)
result = new Tobject();
//apply whatever updates you are wanting to do
//result.SomeField = "bob";
//This will replace or insert data
return BlobCache.LocalMachine.InsertObject(someKEy, result);
})
.Subscribe();
It's really all pretty boring stuff :-p Just get an object and store an object. Under the hood Akavache does a lot of really cool optimizations and synchronizations around that boring stuff though allowing it to be boring for the rest of us
In most of my cases when I start up a VM I retrieve the object from the cache and then just store it as some property on the VM or inside some service class. Then when any changes are made to the object I just insert it into the cache
BlobCache.LocalMachine.InsertObject(someKEy, result).Subscribe()
At that point I know now if the app closes down I'll have the latest version of that object right when user starts up app
The examples I gave are more the full Rx way of accessing... What you have in your original question works fine
await BlobCache.LocalMachine.GetOrFetchObject<List<object>>("CacheItems",
async () => await getdatafromAzure(recursive));
That will basically check the cache if it doesn't exist then it goes to Azure...
LocalMachine stores to physical device, InMemory just stores to some internal dictionary that goes away once the app is unloaded from memory, and UserAccount works with NT remoting accounts.

Where to keep "currentUser" globally accessible

Almost every object in my state tree needs to have the following fields:
createdByGuid
createdAt
modifiedAt
The date fields are easy to add in the action creators. There seems to be consensus that action creators are the place where impureness are allowed, i.e. new Date().
But the currently logged in user is not easily fetched since this data lives in another slice of the state.
Example state:
profile
data
guid
firstname
...
media
items
0: guid, createdByGuid, ...
1: guid, createdByGuid, ...
drawings
items
...
When a MEDIA_ADD action is dispatched I want the action creator to augment the dispatched data with createdById. Current user needs to be fetched from profile.data.guid.
I don't want to bring the state into my action creator. Instead I can use a thunk to get hold of the state via getState(). But this seems to be a clumsy way of getting hold of a simple guid constant (constant for this session). It becomes more clumsy when essentially all of my action creators for adding data to the state needs to be thunks.
I'm inclined to create a separate global singleton object to hold this data and bring this dependency into all of my action creator modules. This seems to be a lot less disturbing dependency in terms of for example testing.
I suppose most Redux users has about the same question regarding current user. What is a good solution?
I'm working in react-native, but I suppose the question applies to most Redux applications.
If someone is interested, I went the singleton way with this. Not a true singleton per definition, but it suits my needs.
When a user logs in I handle this in an asynchronous action creator (a thunk). The thunk calls setGlobalCurrentUser() after successfully authenticating the user with the server.
To get hold of the current user I only have to import currentUserGuid() from currentUser.js and I don't end up in a dependency hell.
currentUser.js:
let _currentUserGuid;
export function currentUserGuid() {
if(!_currentUserGuid) throw new Error('currentUserGuid:: No logged in user')
return _currentUserGuid;
}
export function setGlobalCurrentUser(user) {
if(user) {
_currentUserGuid = user.get('guid')
} else {
_currentUserGuid = null
}
}

Retrieve previously blocked data after login in firebase

The question itself is simple: For a Firebase app, How do you get data that was previously blocked after you login and it is no longer blocked?
As for the details that lead me to ask this question:
In this particular app, I use a simple layout with 2 main sub trees of the root tree, Users and Data. The Data tree is completely readable, anyone can read it at any time. The Users tree is almost the opposite, with the only exception being if you are logged in, then you can read a specific sub tree that is yours only. This leads to the problem that when you go to the page, this data that may be very important to you is blocked until you log in, and there is no way to retrieve it directly. After you log in, however, you now have permission to get that information, but because it was previously blocked, There seems to be no way to extract it.
I have scoured the docs and found only one trigger that might be useful, onAuth(), but even though I can run stuff after login, I cant actually get any data. The best I have gotten so far was a Firebase Reference to the specific sub tree I need, but I cant find any way to actually use that reference to get the Snapshot because it is after the page load. It seems the only option I have is to refresh the page after login and check for login on page load, but that is an awful lot of overhead. Is there some other way to get the data in a tree that you previously did not have permission for after you log in and do have permission to read it? Might there be some reference in the docs I can't find or don't understand that allows me to demand a new snapshot of a fire base reference that is not through triggers that can only be defined on pageload?
Frank van puffelen is right.
It is as simple as:
// setup and other code
ref = new Firebase(URL); //The firebase reference
myuserid = null; //Storage variable
myname = null; //Storage variable
//Other code
//Start of answer code
ref.onAuth(function(authData) { //ON login status change
if (ref.getAuth()) { //Are they logged in
myuserid = authData.uid; //Stores their UID for use
userbase = 'Users/' + authData.uid; //Get path to user info
ref.child(userbase).on("value", function(snapshot, prevChildKey) {
var newData = snapshot.val(); //get data
console.log(newData); //View data, confirmed it was what I wanted
myname = newData.name; //The important data I needed
})
}
})
It seems that so long as this listener is by the other listeners, it works. It runs every time the Authentication is changed, and if they are logged in, attaching a listener to the path with the information and getting it. I am sure there are better ways and probably some problems with this code, but it works for me.

Safe cache-refresh pattern for ASP.net

I've got quite a lot of code on my site that looks like this;
Item item;
if(Cache["foo"] != null)
{
item = (Item)Cache["foo"];
}
else
{
item = database.getItemFromDatabase();
Cache.insert(item, "foo", null, DateTime.Now.AddDays(1), ...
}
One such instance of this has a rather expensive getItemFromDatabase method (which is the main reason it's cached). The problem I have is that with every release or restart of the application, the cache is cleared and then an army of users come online and hit the above code, which kills our database server.
What is the typical method of dealing with these sorts of scenarios?
You could hook into the Application OnStart event in the global.asax file and call a method to load the expensive database calls in a seperate thread when the application starts.
It may also be an idea to use a specialised class for accessing these properties using a locking pattern to avoid multiple database calls when the initial value is null.

Resources