/// <summary> /// Gets a list of objects corresponding to the relevancy of the request. Is async with callback in most cases. /// </summary> /// <typeparam name="T">The type of objects to list</typeparam> /// <param name="list">The list to fetch</param> /// <param name="callback">A callback to handle the requested data. Can be null to just queue update from server or heat up data from disk cache.</param> public static void List <T>(string list, Action <IEnumerable <T> > callback) where T : NetworkDataObject, new() { string eventName = typeof(T).Name + ".list"; int hash = eventName.GetHashCode(); if (CommunicationsApi.IsAvailable) { // fetch array with ids, then Get each object (allows us to fetch from local cache instead of sending buttloads of data over net by default) CommunicationsApi.Socket.Emit(eventName, list, "", o => { CommunicationsApi.RunOnMainThread(() => { List <T> returns = new List <T>(); var got = (o as JsonEncodedEventMessage).GetFirstArgAs <string[]>(); int i = got.Length; foreach (var id in got) { Get <T>(id, obj => { returns.Add(obj); i--; if (i == 0) { if (callback != null) { callback(returns); } } }); } }); }); } else { var cache = OfflineCache.Fetch <T>(hash); if (cache != null) { List <T> returns = new List <T>(); var got = (cache as string[]); int i = got.Length; foreach (var id in got) { Get <T>(id, obj => { returns.Add(obj); i--; if (i == 0) { if (callback != null) { callback(returns); } } }); } } else { if (callback != null) { callback(new T[0]); } } } }
/// <summary> /// Retreives an object from a datasource, depending on the availability. /// </summary> /// <typeparam name="T">Type of object to retreive, must of type NetworkDataObject</typeparam> /// <param name="id">The Id for the object to retreive</param> /// <param name="callback">A callback to handle the retreived data. Can be null to just queue update from server or heat up data from disk cache.</param> public static void Get <T>(string id, Action <T> callback) where T : NetworkDataObject, new() { // we define event as "get Type", needs to be mapped on server as well string eventName = typeof(T).Name + ".get"; // get unique-ish hash key for object int hash = GetHashCode(typeof(T), id); // if object was last modified less than a minute ago, return instantly and queue an update bool fast = false; if (ObjectTracker.ContainsKey(hash) && ObjectTracker[hash].LastModified > (DateTime.UtcNow - TimeSpan.FromMinutes(1))) { if (callback != null) { callback(ObjectTracker[hash] as T); } fast = true; } if (CommunicationsApi.IsAvailable) { // Queue update from server CommunicationsApi.Socket.Emit(eventName, id, "", o => { CommunicationsApi.RunOnMainThread(() => { // New object? create empty instance and merge data to it if (!ObjectTracker.ContainsKey(hash)) { ObjectTracker[hash] = new T(); } ObjectTracker[hash].Merge((o as JsonEncodedEventMessage).GetFirstArgAs <T>()); // Update Offline Cache, is done async so it doesn't block OfflineCache.QueueStore(hash, ObjectTracker[hash]); if (!fast && callback != null) { callback(ObjectTracker[hash] as T); } }); }); } else { if (fast) // fast cache but API offline? not our problem for now { return; } // Got an object tracked but older than a minute? lets just use it if (ObjectTracker.ContainsKey(hash)) { if (callback != null) { callback(ObjectTracker[hash] as T); } return; } // Attempt to fetch sync from Offline Cache var cache = OfflineCache.Fetch <T>(hash); if (cache != null) { ObjectTracker[hash] = cache; if (callback != null) { callback(cache); } return; } else { if (callback != null) { callback(new T()); // returns empty object that is considered unavailable } } } }