I have an ASP.NET webpage that displays steps that must be performed server side. Those steps must be performed in the specified order, and the precedding step must be completed before the next one starts. For example, the steps would be:
1) Performing action A : Completed
2) Performing action B : In progress
3) Performing action C : Waiting
4) Performing action D : Waiting
When a step is completed, the corresponding status (Completed, In progress or Waiting) must be updated on the page.
So, how would you guys do that?
Here's what I have in mind:
The page calls a webmethod that performs the steps server side. When one step is completed, that webmethod updates a session variable that contains the step number and its status.
Then, every 5 seconds or so, the page calls another webmethod that checks the session variable and returns the step numbers that are completed. In javascript, update the status of the steps
Maybe there is a simpler way?
If it is possible that a person may close their browser & the steps should not be repeated, I'd consider using your DB or a cookie for the storage of steps and their corrosponding status.
It's the 'in progress' and 'waiting' that are the major cruxes of your problem as you won't be able to determine their state without some type of polling. I've done similar things before and used effectively the same method you described.
Related
I am having a hard time to understand when to use Initialize and when to use OnNavigatedTo.
I understand that Initialize is execute once when the view model is initialized and OnNavigatedTo is executed every time I navigate to the page.
What is the best way on deciding what to do in Initialize and what to do in OnNavigatedTo?
Especially in a situation where I have data passed by navigation parameters but also fetched from additional apis (some even with http calls that can take a while)
Thanks a lot
Using Initialize will be triggered only when your ViewModel is created meaning you will have to destroy it and recreated it before triggering this method again.
OnNavigatedTo will be triggered every time your page (the one linked to this ViewModel) will appears, meaning it will be the case on the first navigation (same as Initialized) but also every time you will go back to this page.
So if you have the following navigation pattern: Page 1 > Page 2 > Go back to Page 1, Initialized will be triggered only on step 1 (creation of your ViewModel) while OnNavigatedTo will be triggered twice, once in step 1 and the other time on step 3.
I have a scheduled function that runs every three minutes.
It is supposed to look on the database (firestore), query the relevant users, send them emails or perform other db actions.
Once it sends an email to a user, it updates the user with a field 'sent_to_today:true'.
If sent_to_today == true, the function won't touch that user for around 24 hours, which is what's intended.
But, because I have many users, and the function is doing a lot of work, by the time it updates the user with sent_to_today:true, another invocation gets to that user beforehand and processes them for sending emails.
This results in some users getting the same email, twice.
What are my options to make sure this doesn't happen?
Data Model (simplified):
users (Collection)
--- userId (document)
--- sent_to_today [Boolean]
--- NextUpdateTime [String representing a Timestamp in ISO String]
When the function runs, if ("Now" >= NextUpdateTime) && (sent_to_today==false), the user is processed, otherwise, they're skipped.
How do I make sure that the user is only processed by one invocation per day, and not many?
As I said, by the time they're processed by one function invocation (which sets "sent_to_today" to true), the next invocation gets to that user and processes them.
Any help in structuring the data better or using any other logical method would be greatly appreciated.
Here is an idea I'm considering:
Each invocation sets a global document's field, "ex: busy_right_now : true" at the start, and when finished it sets it again to false. If a subsequent invocation runs before the current is finished, it does nothing if busy_right_now is still true.
Option 1.
Do you think you the function can be invoked once in ten minutes, rather every three minutes? If yes - just modify the scheduler, and make sure that 'max instances' attribute is '1'. As the function timeout is only 540 seconds, 10 minutes (600 seconds) is more than enough to avoid overlapping.
Option 2.
When a firestore document is chosen for processing, the cloud function modifies some attribute - i.e. __state - and sets its value to IN_PROGRESS for example. When the processing is finished (email is sent), that attribute value is modified again - to DONE for example. Thus, if the function picks up a document, which has the value IN_PROGRESS in the __state attribute - it simply ignores and continues to the next one.
The drawback - if the function crashes - there might be documents with IN_PROGRESS state, and there should be some mechanism to monitor and resolve such cases.
Option 3.
One cloud function runs through the firestore collection, and for each document, which is to be processed - sends a pubsub message which triggers another cloud function. That one works only with one firestore document. Nevertheless the 'state machine' control is required (like in the Option 2 above). The benefit of the option 3 - higher level of specialisation between functions, and there may be many 'second' cloud functions running in parallel.
I have 2 "limit" queries on the same path. I first load a "limit(1)", and then later load a "limit(50)".
When I load the second query, the child_added events don't fire in-order. Instead, the last item in the list (the one returned by limit(1)) is fired first, and then all of the other items are fired in-order, like this:
**Limit 1:**
new Firebase(PATH).limit(1).on('child_added', ...)
Message 5
**Limit 2:**
new Firebase(PATH).limit(50).on('child_added', ...)
Message 5
Message 1
Message 2
Message 3
Message 4
I'm confused why "Message 5" is being called first in the second limit operation. Why is this happening, and how can I fix it?
I know this may seem strange, but this is actually the intended behavior.
In order to guarantee that local events can fire immediately without communicating with the server first, Firebase makes no guarantees that child_added events will always be called in sort order.
If this is confusing, think about it this way: If you had no internet connection at all, and you set up a limit(50), and then called push() on that reference, you would you expect an event to be fired immediately. When you reconnect to the server though, it may turn out that there were other items on the server before the one you pushed, which will then have their events triggered after the event for the one you added. In your example, the issue has to do with what data has been cached locally rather than something written by the local client, but the same principle applies.
For a more detailed example of why things need to work this way, imagine 2 clients, A and B:
While offline, Client A calls push() and sets some data
While online, Client B adds a child_added listener to read the messages
Client B then calls push(). The message it pushed triggers a child_added event right away locally.
Client A comes back online. Firebase syncs the data, and client B gets a child_added event fired for that data.
Now, note that even though the message Client A added comes first in the list (since it has an earlier timestamp), the event is fired second.
So as you see, you can't always rely on the order of events to reflect the correct sort order of Firebase children.
But don't worry, you can still get the behavior you want! If you want the data to show up in sort order rather than in the order the events arrived on your client, you have a couple of options:
1) (The naive approach) Use a "value" event instead of child_added, and redraw the entire list of items every time it fires using forEach. Value events only ever fire for complete sets of data, so forEach will always enumerate all of the events in order. There's a couple of downsides to this approach though: (1) value events won't fire until initial state is loaded from the server, so it won't work if the app is started in "offline mode" until a network connection can be established. (2) It inefficiently redraws everything for every change.
2) (The better approach) Use the prevChildName argument in the callback to on(). In addition to the snapshot, the callback for on() is passed the name of the previous child in in the query when items are placed in sort order. This allows you to render the children in the correct order, even if the events are fired out of order. See: https://www.firebase.com/docs/javascript/firebase/on.html
Note that prevChildName only gives the previous child in the query, not in the whole Firebase location. So the child at the beginning of the query will have a prevChildName of null, even if there is a child on the server that comes before it.
Our leaderboard example shows one way to manipulate the DOM to ensure things are rendered in the proper order. See:
https://www.firebase.com/tutorial/#example/leaderboard
I have a method , it takes some time like 4 minutes , for that i want show a text in the page about completion of method like for 1 min, 2 min, 3 min and some data i want to store session and that i want to access in ajax timer and want to show the status of the method like completion state for make user to understand how much the method completed.
Thanks
Use the HeartBeat design pattern.
Your javascript will call a custom HTTP handler thru Ajax calls (every x seconds), and that handler will return status information to the javascript using JSON data. Next, you will update your progress control according to that data.
I have a web service with three methods: StartReport(...), IsReportFinished(...) and GetReport(...), each with various parameters. I also have a client application (Silverlight) which will first call StartReport to trigger the generation of the report, then it will poll the server with IsReportFinished to see if it's done and once done, it calls GetReport to get the report. Very simple...
StartReport is simple. It first generates an unique ID, then it will use System.Threading.Tasks.Task.Factory.StartNew() to create a new task that will generate the report and finally return the unique ID while the task continues to run in the background. IsReportFinished will just check the system for the unique ID to see if the report is done. Once done, the unique ID can be used to retrieve the report.
But I need a way to cancel the task, which is implemented by adding a new parameter to IsReportFinished. When called with cancel==true it will again check if the report is done. If the report is finished, there's nothing to cancel. Otherwise, it needs to cancel the task.
How do I cancel this task?
You could use a cancellation token to cancel TPL tasks. And here's another example.