I am developing an application on Azure Service fabric. Its a simple User TODO application. I created TodoActor to add User TODO. It simply adds the User TODO using StateManager. I am aware that the StateManager will store the State in disk memory and not in any database.
But before starting the Application, I want that user should have preloaded Todos for them. Is there any way to have preloaded States for actor?
Is there any way to have this data in Database?
Actors are created when they are used. So for example, when it is called, or when a reminder triggers. If an Actor was never used before, it doesn't exist yet, so there is no way to pre-load state.
What you can do is pre-load data just-in-time when the Actor is created:
protected override async Task OnAactivateAsync()
{
if(!await StateManager.ContainsStateAsync("ToDoState"))
{
await this.StateManager.TryAddStateAsync<List<string>>("ToDoState", new List<string>{});
}
}
Related
Let's say we have a Flutter app where we want to save some persistent data using shared preferences.
(We don't want to save the data persistently every time the user changes it because the UI depends directly on the data, and in order to save it we need to use await async, and that lags the UI), so we use WidgetsBindingObserver to detect when the app goes to the background in order to use that event as an efficient catch-all opportunity to save the data.
So, we have some code like this in the root page of our app:
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
if (state == AppLifecycleState.paused) {
// went to Background
myPersistentData.instance.write(); // <-------------- this is an async operation
}
if (state == AppLifecycleState.resumed) {
// came back to Foreground
}
}
This seems to work, but I'm concerned that the lifecycle could progress beyond "paused" (pause>stop>finish) so quickly that this "trailing" operation doesn't have time to finish... and thus the data would not be saved.
Is this a legitimate concern?
I would say as much as possible try to avoid calling async operations in the dispose or lifecycle methods of widgets, while you may be concerned that it may/may not complete i would recommend like the dart docs states here: https://api.dart.dev/stable/2.14.1/dart-async/unawaited.html, "Not all futures need to be awaited.", "You should use unawaited to convey the intention of deliberately not waiting for the future.". But generally, i'd avoid calling async functions in these methods.
It should be a concern for sure because the time available for an app to run in background is limited and not defined.
Based on the memory resources needed for the most important app, which is the one in foreground, the system may kill your app faster or at a later point in time. In either scenarios you don't have much time to complete the tasks, this event should be used to do fast clean up like killing tasks that are started, clearing token or maybe saving a token or a session info.
There are also scenarios which will cause problems for this approach, like the pone runs out of battery or the OS crashes, in this case you don't have any notification of app going into bg. Or the user force quits your app.
In your case, I would say you have another concern, saving data in shared preferences shouldn't affect your UI only if:
you save it synchronously which is a no no
you save a huge chunk of data in shared prefs, in this case you should use a database.
and a less likely scenario, you have a race condition while you save in shared prefs which are not thread safe.
I would suggest to rethink a bit your approach on this matter, maybe you can spawn async operations that save the data in certain points of the app (user exits a screen or whatever) while also keeping a copy in memory. Maybe is better to save it using a database. In the end is your decision, but my advice would be, don't rely on the app running in bg time.
For something like this, there is no way you can continue a service purely in Flutter. That's bummer of course but there are work-arounds you can use to do that.
If you want to approach this problem in a more convenient but difficult way, you can always create a service in native (Kotlin/Java in case of Android or Swift/Objective-C for iOS) and call your native functions using MethodChannels. Your native service can be alive even if you kill your app. Think of Push-notifications service where even if you kill your app, Push service is always alive to serve your notification.
The Bloc manual describes the example of a simple Todos app. It works as an example, but I get stuck when trying to make it into a more realistic app. Clearly, a more realistic Todos app needs to keep working when the user temporarily loses network connection, and also needs to occasionally check the server for updates that the user might have added from another device.
So as a basic data model I have:
dataFromServer, which is refreshed every five minutes, and
localData, that describes what changes have been made locally but haven't been synchronized to the server yet.
My current idea is to have three kinds of events:
on<GetTodosFromServer>() which runs every few minutes to check the server for updates and only changes the dataFromServer,
on<TodoAdded>() (and its friends TodoDeleted, TodoChecked, and so on) which get triggered when the user changes the data, and only change the localData, and
on<SyncTodoToServer>() which runs whenever the user changes the todo list, or when network connectivity is restored, and tries to send the changes to the server, retrieves the new value from the server, and then sets the new dataFromServer and localData.
So obviously there's a lot of interaction between these three methods. When a new todo is added after the synchronization to the server starts, but before synchronization is finished, it needs to stay in the local changes object. When GetTodosFromServer and SyncTodoToServer both return server data, they need to find out who has the latest data and keep that. And so on.
Coming from a Redux background, I'm used to having two reducers (one for local data, one for server data) that would only respond to simple actions. E.g. an action { "type": "TodoSuccessfullySyncedToServer", uploadedData: [...], serverResponse: [...] } would be straightforward to parse for both the localData and the dataFromServer reducer. The reducer doesn't contain any of the business logic, it receives actions one by one and all you need to think about inside the reducer is the state before the action, the action itself, and the state after the action. Anything you rely on to handle the action will be in the action itself, not in the context. So different pieces of code that generate those actions can just fire these actions without thinking, knowing that the reducer will handle them correctly.
Bloc on the other hand seems to mix business logic and updating the state. API calls are made within the event handlers, which will emit a value possibly many seconds later. So every time you return from an asynchronous call in an event handler, you need to think about how the state might have changed while that call was happening and the consequences this has on what you're currently doing. Also, an object in the state can be updated by different events that need to coordinate among themselves how to avoid conflicts while doing so.
Is there a best practice on how to avoid the complexity that brings? Is it best practice to split large events into "StartSyncToServer" and "SuccessfullySyncedToServer" events where the second behaves a lot like a Redux reducer? I don't see any of that in the examples, so is there another way this complexity is typically avoided in Bloc? Or is Bloc entirely unopinionated on these things?
I'm not looking for personal opinions here, only if there's something I missed in the Bloc manual (or other authoritative source) about how this was intended to work.
I have a Web Api stateless service that is creating an Actor that does some long running processing via a reminder (fire and forget). It stores its own progress in local state. I am unable to get the progress of that long running process due to the single threaded nature of the Actor, any call to the method that gets the progress will wait until the long running process has completed. Does anyone have a solution for this (without using an external data source)?
If you simply wish to get the current state of your Actor without having to wait for an Actor lock you can actually use the underlying ActorService that is hosting the Actors to query the state without interrupting, or being blocked by the long running Actor method.
The ActorService hosting Actors is really just a StatelessService (with some bells and whistles) and you can communicate with it the same way you would communicate with any Service - add an IService interface to it and the use IServiceProxy to talk to it. This SO Answer shows how you can do that How to get state from service fabric actor without waiting for other methods to complete?
If you want to get progress along the way even during the execution of your Actor method you can force a save of the state changes in the middle of your long running exectuion by calling SaveStateAsync
You could create a ProgressTrackingActor and periodically update it from the existing Actor. Query the ProgressTrackingActor for progress.
You can use an ActorReference to indicate which Actor to query progress for, or use the same ActorId value.
To be specific, I need to create an array variable that will be used for caching data, but I don't want to use ZF2 Cache Adapter.
I've tried to create a invokable class that would be used to instantiate object of my class that contains methods for setting and getting values from array that is also defined as a property of that class. As far as I understand, service manager treats all services as shared by default, which is supposed to create only one instance off my class when I get the service by service manager method get for the first time. But this doesn't work, if I get that service in different actions in my Controller class, which is what I need to do. So, how am I supposed to achieve this effect? Create an object that is available application-wide?
I had this kind of problem with managing a cart.
My cart is modeled by a CartManager, which is a unique instance for a user (session) and until paiement (cart is persisted in database).
I register my CartManager as a Service to build the first instance, this instance is built during an event handler attached on MvcEvent::EVENT_ROUTE, once built I override the CartManager service with my Instance, this way wherever I call the service, my first instance is served.
Then I persist (session or database) my Instance in an other event handler attached on MvcEvent::EVENT_FINISH.
All the event handlers are attached in Module::onBoostrap()
I have a program with about 8 Activity classes, and 1 Application class. I want my Application class to be able to communicate with every Activity, but on its own terms. I don't want the activity to ask the Application for data, I want the Application to send the Activity data. The problem with this, is that depending on the current state of the program I'm unsure what Activity will be open.
Is there a method of some sort which will send information from the Application to the CURRENT activity?
The Application class connects with an embedded Bluetooth Device and needs to receive different pieces of data depending on which Activity the user is currently in. I originally had it as a regular class, which was initialized in the MainMenu of my program and passed a Handler. However, it seemed like weak design to pass that Handler from Activity to Activity time and time again.
You could use a Callback Method
Every Activity has it's own callback method and registers that method onResume() in the Application Class. (it's like an onApplicationWantsToDoSomethingWithMeListener() ;)
or why not a Service in background? instead of the Application, since what you want sounds like a Service. More details?
EDIT:
I made a similar application with bluetooth, you should definetly use a Service for that, but you can communicate with your service per Application. Say the Service calls the callback in the Application look here for an implementation uf such a thing