Falcor Model with Cache data from External Api - falcor

How will the json data sent over from external Api be cached into the Falcor-Model? Also, how to specify in the Model to hit the external Api again if data not present in the cache?
My doubt was partially answered in one of the posts:
How does Falcor cache data in the server side?
So now I understand that Falcor-Model cache works only at the client side, which is fine. But how will the Model work if the data is not present in the cache?
var model = new falcor.Model({source: new falcor.HttpDataSource('http://localhost/rating.json') });
model.
get("rating").
then(function(response) {
document.getElementById('filmRating').innerText = JSON.stringify(response.json.rating,null, 4);
});
Here the response is a json object, which can be put into a Falcor-Model cache and stored globally in the client side. But how can the Model be triggered again if data not present in cache?

The main advantage of using Falcor is that you should not have to care whether data is present in cache or fetched from the server, because model.get() which fetch all the data missing in the cache from the server by making an HTTP request.
So, the first model.get(path) query will fetch from server, and put response in cache. If you call model.get(path) again, it will be served from the cache.

Related

Workbox: how to remove a request from the cache

I'm using staleWhileRevalidate Workbox v3 strategy for all of my API Get calls. However, sometimes I want to remove a particular request from the cache at runtime.
Example: I have a yes/no state that can be updated by the client. Initially, the UI displays the "no" state (taken from the cache) while executing a request that also returns a "no" result. The result of the request is cached by Workbox.
Now, the user switches it to "yes", the system updates the server and sends another query after some time to get the latest value. But the cache still stores the "no" value which is displayed in the UI while the new request returns "yes" which is now stored in the cache.
What I need here is to remove the "no" result from the cache right when I send the update request from the server. How do I do that? How can I access the Workbox's cache from the page code?
Workbox uses the browser's Cache Storage API for its caching. You can access the same caches directly, either via the window context or inside of a service worker, from your own code.
It's easier to do this if you configure your Workbox strategy to use a specific cache name, rather than the default cache name, since you'd otherwise need to reverse-engineer some of the Workbox logic to create the default cache name inside of the window context. Assuming you know the cache name and the URL to delete, you can call the following function from within the window context to use the Cache Storage API to delete the entry:
async function deleteFromCache(cacheName, urlOrPath) {
const cache = await caches.open(cacheName);
await cache.delete(urlOrPath);
}
// Later:
await deleteFromCache('runtime-cache', '/path/to/entry');

What is the difference between new sap.ui.model.odata.ODataModel and read?

I am playing around with a OData service and I am very confused when to use this
var oModel = new sap.ui.model.odata.ODataModel("proxy/http/services.odata.org/V3/(S(k42qhed3hw4zgjxfnhivnmes))/OData/OData.svc");
this.getView().setModel(oModel);
vs
var oModel = new sap.ui.model.odata.ODataModel("odatserviceurl", true);
var productsModel = new JSONModel();
oModel.read("/Products",
null,
null,
false,
function _OnSuccess(oData, response) {
var data = { "ProductCollection" : oData.results };
productsModel.setData(data);
},
function _OnError(error) {
console.log(error);
}
);
this.getView().setModel(productsModel);
I have two working example using both approach but I am not able to figure out why using read method if I can achieve same with first version. Please explain or guide me to the documentation which can clear my confusion.
Ok, lets start with the models:
JSON Model : The JSON model is a client-side model and, therefore, intended for small datasets, which are completely available on the client. The JSON model supports two-way binding. NOTE: no server side call is made on filtering, searching, refresh.
OData Model : The OData model is a server-side model: the dataset is only available on the server and the client only knows the currently visible rows and fields. This also means that sorting and filtering on the client is not possible. For this, the client has to send a request to the server. Meaning searching/filtering calls odata service again.
Now, lets look at scenarios where we will use these models:
Scenario 1: Showing data to user in a list/table/display form. Data manipulation is limited to searching and filtering. Here, I would use oData model directly to controls as only fetching of data is required.( your method 1) (NOTE: One way binding). Remember here all changes require a call to server.
Scenario 2: I have an application which has multiple inputs, user can edit changes, also some fields are calculated and mandatory. All in all, many user changes are done which may be temporary and user might not want to save them. Here, you dont want to send these temporary changes to backend as yet. You way want to manipulate, validate data before sending. Here, we will use JSON Model after reading data from odata model ( your method 2). Store the changes in local JSON model, validate and manipulate them and finally send the data using Odata create/update. Remember here all changes DO NOT require a call to server as data is present in local JSON MODEL.
Let me know if this helps you. :)
EDIT : Additional Information :
As per your comment :
Documentation says oModel.read' trigger get request but new sap.ui.model.odata.ODataModel("proxy/http/services.odata.org‌​/V3/(S(k42qhed3hw4zg‌​jxfnhivnmes))/OData/‌​OData.svc")` does the same thing so why and when to use oModel.read
Here, is where you misunderstood. The code
new sap.ui.model.odata.ODataModel("proxy/http/services.odata.org‌​/V3/(S(k42qhed3hw4zg‌​jxfnhivnmes))/OData/‌​OData.svc") will NOT send a read/get Request. It calls the odata services and fetches the metadata of the service. A service can have multiple entities.
For example: the service :http://services.odata.org/Northwind/Northwind.svc/ has mutiple entity sets such as Categories, Customers, Employees etc. So, when I declare : new sap.ui.model.odata.ODataModel("http://services.odata.org/Northwind/Northwind.svc/") it will fetch the metadata for service (not actual data). Only when you call the desired entity set, it will fetch the data. The Entity set is specified :
When you call the read method ( like you have specified '/Products')
Bind the entity set name directly to control like to List,Table etc ( items='{/Products}' )

Best way to Cache JSON from API in SWIFT?

I need to cache json data from API in swift.
So I researched a Lot & get to this Post.
I tried to implement the Option 1 in my App. But the Custom manager always returned nil. I don't know why?
After that I got AwesomeCache. It says that it an do Awesome API Caching.
But I don't know how to implement this?
I referred this Issue. Still I can't figure it Out.
This is how my Current implementation Looks without Cache:
Alamofire.request(.GET, "http://api.androidhive.info/volley/person_array.json")
.responseJSON { (_, _, data, _) in
let json = JSON(data!)
let catCount = json.count
for index in 0...catCount-1 {
let name = json[index]["name"].string
println(name)
}
Please suggest me the Best way to Cache JSON from API ?
Thanks in Advance!
UPDATE
These are my requirements
Fetch the JSON from the API & Parse the JSON data. These can be done with the help of Alamofire & SwiftyJSON
I will populate the parsed data in the Table View. It works when the user is in Online.
But I want to show the data in the Table when the user is in offline too.
So I need to save the Parsed data or the JSON data in my cache & I need to refresh or expire the cache within a week or days.
I don't prefer to store the JSON in my disk because it will be updated.
Please suggest me the Best way to achieve this...
You have many tools already at your disposal.
NSURLCache
All your requests are already stored in the NSURLCache in the NSURLSessionConfiguration on the NSURLSession stored inside the sharedInstance of the Alamofire Manager. Those stored requests already follow all the caching policy rules provided by the servers you are hitting. You can control the caching behavior by setting the requestCachePolicy on your own custom NSURLSessionConfiguration. I'd also suggest you read through this awesome NSHipster article that walks you through the ins and outs of NSURLCache and how to control it.
Creating custom Manager objects is covered in the current Alamofire docs.
Downloading JSON to Disk
You can also download the JSON directly to disk using Alamofire.download instead of using Alamofire.request. This will download the payload to a fileURL that you provide in the destination closure. This would give you full control over the caching of the file after that point. You would need to create your own caching policy around these files afterwards if you wanted to follow the caching header rules provided by the server.
Populating Table View
Once you have your data downloaded to disk, you need to load it into an NSData blob and parse it into JSON to populate your table view. This should be pretty straight forward. You need the destination NSURL that you specified to Alamofire when you started your download. Then load the file data into an NSData blob. Finally, use NSJSONSerialization to convert the NSData object into a JSON AnyObject which can be parsed into model objects to populate your table view.
Obviously you don't "have" to parse the JSON into model objects, but this helps protect your table view from malformed JSON data.
Storing JSON for Offline Usage
If you stick with this approach, you'll need to track your cache expiration dates in something like CoreData or SQLite. You can do this by either caching the paths to the JSON files on disk, or store the model objects directly in CoreData or SQLite. This could get fairly complicated and I would not recommend this approach unless you absolutely don't want to cache your model objects.
Offline Usage
Generally, if you need to cache data for offline usage, you want to store your model objects in something like CoreData. You would use the Alamofire request method coupled with a responseJSON serializer to parse the data into JSON. Then you would convert the JSON into model objects. From there, you'd save your model objects in CoreData, then finally populate your table view with the model objects.
The nice thing about this approach is that you have all your model objects cached in the case that your table view is accessed when the device is offline. Coupling this design with queries to your NSURLCache to see if your request is cached let's you avoid unnecessary server calls and parsing logic when you already have your model objects generated.
Given the updates to your original question, I would recommend this approach.
You can use this cache open source. It cache data on disk and memory. Can cache many swift type, and custom class which inherit NSObject and conform NSCoding protocol.
https://github.com/huynguyencong/DataCache
To implement:
First, it use NSCache for mem cache. NSCache use like a dictionary.
Second, save cache to disk, use NSFileManager methods.

MVC 3 - Sessionless controllers datastore options

i've been reading about sessionless controllers lately and it seems an interesting idea, since it improves perfomance and let ajax calls to be asynchronous, as usually they should be.
However, i can't figure a nice way to store data that would previously stored by a session. I have a lot of single-fetch data that i get once and walks with it through several pages. My first thought was to use MemoryCache, but reading this post i begin to doubt it, since IIS can let go my data anytime.
Because of this, i got a little confused on what should i do to store data in a session like way. I read a couple of thing about NoSQL and MongoDB, but wouldn't that be the same as to fetch data all the time i need it?
Can you give me some clarifications and technologies i can use to serve as temporary datastore?
Have you considered using the HttpContext.Cache? As you're saying in a session like way, there is no reason you couldn't create a cache key based upon the sessionid of the current request:
// cache key
var cacheKey = string.Format("{0}-{1}", "SomeKey", Session.SessionID);
// save to cache
HttpContext.Cache.Insert(cacheKey, <yourobject>, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20));
From there it would simply be a matter of passing along the sessionid and retrieving at a later time:
HttpContext.Cache[cacheKey]

How can I store user information in MVC between requests

I have an MVC2-site using Windows authentication.
When the user requests a page I pull some user information from the database. The class I retrieve is a Person class.
How can get this from the database when the user enters the site, and pick up the same class without touching the db on all subsequent page requests?
I must admit, I am pretty lost when it comes to session handling in ASP.net MVC.
You can store that kind of information in HttpContextBase.Session.
One option is to retrieve the Person object from your database on the first hit and store it in System.Web.HttpContext.Current.Cache, this will allow extremely fast access and your Person data will be temporarily stored in RAM on the web server.
But be careful: If you are storing significantly large amount of user data in this way, you could eat up a lot of memory. Nevertheless, this will be perfectly fine if you only need to cache a few thousand or so. Clearly, it depends upon how many users you expect to be using your app.
You could add like this:
private void CachePersonData (Person data, string storageKey)
{
if (HttpContext.Current.Cache[storageKey] == null)
{
HttpContext.Current.Cache.Add(storageKey,
data,
null,
Cache.NoAbsoluteExpiration,
TimeSpan.FromDays(1),
CacheItemPriority.High,
null);
}
}
... and retrieve like this:
// Grab data from the cache
Person p = HttpContext.Current.Cache[storageKey];
Don't forget that the object returned from the cache could be null, so you should check for this and load from the database as necessary (then cache).
First of all, if you are using a load balanced environment, I wouldn't recommend any solution that you try without storing it in a database, because it will eventually fail.
If you are not in a load balancing environment, you can use TempData to store your object and then retrieve it in the subsequent request.
HttpContext.Current.Session[key];

Resources