What impact does changing a IReliableQueue to a IReliableConcurrentQueue have in an existing deployment? - azure-service-fabric

I am working in a Service Fabric application that uses IReliableQueue. For the uses cases of this system, the IReliableConcurrentQueue makes sense to use and some local testing (i.e. basically by just changing the code to use IReliableConcurrentQueue instead of IReliableQueue - queue name does not change) shows great performance improvements. However, I am worried about the impact of changing this in a production system (i.e. upgrading). I can't find any docs or online questions (unless I just missed them) about these considerations. For example, in this system, the existing IReliableQueue will almost always have items. So what happens to that data when I upgrade the SF application? Will it be available to dequeue in the IReliableConcurrentQueue? Or would data be lost? I know I can "just try it" but wanted to see if someone out there had done the same or could offer pointers to existing resources. Thanks!

Sorry for a late answer (that you probably don't need anymore but still).
When we calling GetOrAddAsync method on IReliableStateManager we aren't retrieving the interface to store values - we actually creating an instance of reliable collection. This basically means that type of the interface we specify is very important.
Taking this into account if we do this:
Service v. 1.0
// Somewhere in RunAsync for example
await this.StateManager.GetOrAddAsync<IReliableQueue<long>>("MyCollection")
Then doing this in the next version:
Service v. 1.1
// Somewhere in RunAsync for example
await this.StateManager.GetOrAddAsync<IReliableConcurrentQueue<long>>("MyCollection")
will throw an exception:
Returned reliable object of type Microsoft.ServiceFabric.Data.Collections.DistributedQueue`1[System.Int64] cannot be casted to requested type Microsoft.ServiceFabric.Data.Collections.IReliableConcurrentQueue`1[System.Int64]
and then:
System.ExecutionEngineException: 'Exception of type 'System.ExecutionEngineException' was thrown.'
The above exception looks like a bug so I have filled one.
UPDATE 2019.06.28
It turned out that appearance of System.ExecutionEngineException isn't a bug but rather an undocumented behavior of Environment.FailFast method in combination with Visual Studio debugger.
Please see my comment to the above issue.
This is what would happen.
There are plenty ways to overcome this.
Here is the most obvious one:
Example
var migrate = false; // This flag indicates whether the migration was already done.
var migrateValues = new List<long>();
var applicationFlags = await this.StateManager
.GetOrAddAsync<IReliableDictionary<string, bool>>("application-flags");
using (var transaction = this.StateManager.CreateTransaction())
{
var flag = await applicationFlags
.TryGetValueAsync(transaction, "queue-to-concurrent-queue-migration");
if (!flag.HasValue || !flag.Value)
{
var queue = await this.StateManager
.GetOrAddAsync<IReliableQueue<long>>("value-collection");
for (;;)
{
var c = await queue.TryDequeueAsync(transaction);
if (!c.HasValue)
{
break;
}
migrateValues.Add(c.Value);
}
migrate = true;
}
}
if (migrate)
{
await this.StateManager.RemoveAsync("value-collection");
using (var transaction = this.StateManager.CreateTransaction())
{
var concurrentQueue = await this.StateManager
.GetOrAddAsync<IReliableConcurrentQueue<long>>("value-collection");
foreach (var i in migrateValues)
{
await concurrentQueue.EnqueueAsync(transaction, i);
}
await applicationFlags.AddOrUpdateAsync(
transaction,
"queue-to-concurrent-queue-migration",
true,
(s, b) => true);
}
await transaction.CommitAsync();
}
Please note that this code is just an illustrative example and should be properly tested before applying it to real life application.

Related

async/await - calling an async API from a syncronous method using dart [duplicate]

I'm on the way to evaluate Dart for a German company by porting various Java programs to Dart and compare and analyze the results. In the browser Dart wins hands down. For server software performance seemed to be a serious isssue (see this question of me) but that got mostly defused.
Now I'm in the area of porting some "simple" command-line tools where I did not expect any serious problems at all but there is at least one. Some of the tools do make HTTP requests to collect some data and the stand-alone Dart virtual machine only supports them in an asynchronous fashion. Looking through all I could find it does not seem to be possible to use any asynchronous call in a mostly synchronous software.
I understand that I could restructure the available synchronous software into an asynchronous one. But this would transform a well-designed piece of software into something less readable and more difficult to debug and maintain. For some software pieces this just does not make sense.
My question: Is there an (overlooked by me) way to embed an asynchronous call into a synchronously called method?
I imagine that it would not be to difficult to provide a system call, usable only from within the main thread, which just transfers the execution to the whole list of queued asynchronous function calls (without having to end the main thread first) and as soon as the last one got executed returns and continues the main thread.
Something which might look like this:
var synchFunction() {
var result;
asyncFunction().then(() { result = ...; });
resync(); // the system call to move to and wait out all async execution
return result;
}
Having such a method would simplify the lib APIs as well. Most "sync" calls could be removed because the re-synchronisation call would do the job. It seems to be such a logical idea that I still think it somehow exists and I have missed it. Or is there a serious reason why that would not work?
After thinking about the received answer from lm (see below) for two days I still do not understand why the encapsulation of an asynchronous Dart call into a synchronous one should not be possible. It is done in the "normal" synchronous programing world all the time. Usually you can wait for a resynchronization by either getting a "Done" from the asynchronous routine or if something fails continue after a timeout.
With that in mind my first proposal could be enhanced like that:
var synchFunction() {
var result;
asyncFunction()
.then(() { result = ...; })
.whenComplete(() { continueResync() }); // the "Done" message
resync(timeout); // waiting with a timeout as maximum limit
// Either we arrive here with the [result] filled in or a with a [TimeoutException].
return result;
}
The resync() does the same that would normally happen after ending the main method of an isolate, it starts executing the queued asynchronous functions (or waits for events to make them executable). As soon as it encounters a continueResync() call a flag is set which stops this asynchronous execution and resync() returns to the main thread. If no continueResync() call is encountered during the given timeout period it too aborts the asynchronous execution and leaves resync() with a TimeoutException.
For some groups of software which benefit from straight synchronous programing (not the client software and not the server software) such a feature would solve lots of problems for the programer who has to deal with asynchrounous-only libraries.
I believe that I have also found a solution for the main argument in lm's argumentation below. Therefore my question still stands with respect to this "enhanced" solution which I proposed: Is there anything which really makes it impossible to implement that in Dart?
The only time that you can wrap an async method in a synchronous one is when you don't need to get a return value.
For example if you want to disable the save button, save results to the server asynchronously and re-enable the save button when the job is done you can write it like this:
Future<bool> save() async {
// save changes async here
return true;
}
void saveClicked() {
saveButton.enabled = false;
save()
.then((success) => window.alert(success ? 'Saved' : 'Failed'))
.catchError((e) => window.alert(e))
.whenComplete(() { saveButton.enabled = true; });
}
Note that the saveClicked method is fully synchronous, but executes the save method asynchronously.
Note that if you make saveClicked async, not only do you have to call it using the async pattern, but the entire method body will run asynchronously so the save button will not be disabled when the function returns.
For completeness the async version of saveClicked looks like this:
Future<Null> saveClicked() async {
saveButton.enabled = false;
try {
bool success = await save();
window.alert(success ? 'Saved' : 'Failed');
}
catch (e) {
window.alert(e);
}
finally {
saveButton.enabled = true;
}
}
Yes, this is way late, but I think this is a cool feature new people should know about.
There is a way, but the Dart docs warn against it (and it's somehow "experimental", although the implications aren't really discussed).
The waitFor command.
You basically pass in an asynchronous function that returns a Future, an optional timeout parameter, and the waitFor function will return the result.
For example:
final int number = waitFor<int>(someAsyncThatReturnsInt);
The resync function cannot be implemented in Dart's current execution model.
Asynchronous execution is contagious. A synchronous function must return before any other asynchronous events can execute, so there is no way to synchronously wait for asynchronous execution.
Execution in Dart is single-threaded and event based. There is no way for the resync function to block without it also blocking all other execution in the same isolate, so the pending async operations will never happen.
To block the synchronous execution, and continue executing something else, you need to preserve the entire call stack up to that point, and reinstate it later when the synchronous operations have completed. If you have that functionality, then there are probably better ways to do things than Future and Stream :)
Also, waiting for "all async execution" isn't well-defined in an event based system. There might be a broadcast Stream emitting events coming in from the network, a periodic timer, or a receive port getting data from another isolate, or some other source of events that you can't wait for because they come from outside the isolate, or event the process. When the current isolate shuts down, it might send a final shut-down message to another isolate, so effectively the "async execution" isn't over until the isolate dies.
Using the async/await syntax, you won't get synchronous operation, but it will be easier to code the similar asynchronous operation:
function() async {
var result = await asyncFunction();
return result;
}
It won't wait for async operations that aren't reflected in the Future returned by asyncFunction, but that's the job of asyncFunction to not complete until its operations are complete.
Dart is inherently async. Trying to avoid asynchronity won't work out.
There are sync versions of some API calls for example in dart:io and in some situations it might seem simpler to use them instead but because there aren't sync versions for all methods/functions you can't avoid async entirely.
With the recent introduction of the async/await feature programming async become much simpler and the code looks almost like sync code (but it isn't).
If a call went async it stays async. As far as I know there is nothing you can do about it.
import 'package:synchronized_lite/synchronized_lite.dart';
import 'dart:async';
// Using Lock as a mixin to further mimic Java-style synchronized blocks
class SomeActivity with Lock {
bool _started = false;
Future<bool> start() async {
// It's correct to return a Future returned by synchronized()
return synchronized(() async {
if(_started)
return false;
// perform the start operation
await Future.delayed(Duration(seconds: 1));
print("Started");
_started = true;
return true;
});
}
Future<void> stop() async {
// It's also correct to await a synchronized() call before returning
// It's incorrect to neither await a synchronized() call nor return its Future.
await synchronized(() async {
if(!_started)
return;
// perform the stop operation`enter code here`
await Future.delayed(Duration(seconds: 1));
print("Stopped");
_started = false;
});
}
}
// Prints:
// Started
// Stopped
main() async {
var a = SomeActivity();
print("Hello");
a.start();
a.start();
a.stop();
await a.stop();
}
/*Since the Await statement can be used in only asynchronous methods. Then we do two methods.I thinking first we call the async method and then we constantly query the null result for the non-async method. Then we get a synchronized model. In this way, we will wait for the answer in the non-async method. Such a method comes to my mind. But as far as I can see, there is no escape from the async working model in flutter dart language. Need to get used to it.It may be unprofessional, but I wanted to share the solution that came to my mind. hope it helps.
Stock resultStockQueryByBarcodeAsync;
bool waitStockQueryByBarcodeAsyncCompleted = false;
Stock WaitStockQueryByBarcodeAsync(String barcode, int timeOut) {
CallStockQueryByBarcodeAsync(barcode);
var startTime = new DateTime.now();
while (!waitStockQueryByBarcodeAsyncCompleted) {
Duration difference = DateTime.now().difference(startTime);
if (difference.inMilliseconds > timeOut) {
throw TimeoutException("Timeout Exceeded");
}
//we must scope time. Because it can be enter endless loop.
}
return resultStockQueryByBarcodeAsync;
}
void CallStockQueryByBarcodeAsync(String barcode) async {
waitStockQueryByBarcodeAsyncCompleted = false;
resultStockQueryByBarcodeAsync = null;
var stock = await StockQueryByBarcodeAsync(barcode);/*your target async method*/
waitStockQueryByBarcodeAsyncCompleted = true;
resultStockQueryByBarcodeAsync = stock;
}
In my case, I had to initialize the database connection from constructor. I am pretty new in Flutter and I don't know what are the best practices right now. But, here is what I did.
class Storage {
late Database database;
Storage() {
getConnection().then((value) => database = value);
}
Future<Database> getConnection() async {
return await openDatabase('ims.db');
}
}
All I have done, is used the callback method to assign the value when the value is available.
Here's a solution based on staggering the start of the async function with start times at least 1 second apart, when calls come in almost simultaneously.
Steps:
Use the lastKnownTime to calculate the delta, where the initial value is 0
Once the delta is not some huge number, you know it's a duplicate call.
class StartConversationState extends State<StartConversationStatefulWidget> {
#override
Widget build(BuildContext context) {
_delayPush(); // this is the call that gets triggered multiple times
}
int lastKnownTime = 0;
int delayMillis = 3000;
_delayPush() async {
delayMillis += 1500;
await new Future.delayed(Duration(milliseconds: delayMillis));
int millisSinceEpoch = new DateTime.now().millisecondsSinceEpoch;
int delta = millisSinceEpoch - lastKnownTime;
// if delta is less than 10 seconds, means it was a subsequent interval
if (delta < 10000) {
print('_delayPush() , SKIPPING DUPLICATE CALL');
return;
}
// here is the logic you don't want to duplicate
// eg, insert DB record and navigate to next screen
}

Azure Mobile Services for Xamarin Forms - Conflict Resolution

I'm supporting a production Xamarin Forms app with offline sync feature implemented using Azure Mobile Services.
We have a lot of production issues related to users losing data or general instability that goes away if the reinstall the app. After having a look through, I think the issues are around how the conflict resolution is handled in the app.
For every entity that tries to sync we handle MobileServicePushFailedException and then traverse through the errors returned and take action.
catch (MobileServicePushFailedException ex)
{
foreach (var error in ex.PushResult.Errors) // These are MobileServiceTableOpearationErrors
{
var status = error.Status; // HttpStatus code returned
// Take Action based on this status
// If its 409 or 412, we go in to conflict resolving and tries to decide whether the client or server version wins
}
}
The conflict resolving seems too custom to me and I'm checking to see whether there are general guidelines.
For example, we seem to be getting empty values for 'CreatedAt' & 'UpdatedAt' timestamps for local and server versions of the entities returned, which is weird.
var serverItem = error.Result;
var clientItem = error.Item;
// sometimes serverItem.UpdatedAt or clientItem.UpdatedAt is NULL. Since we use these 2 fields to determine who wins, we are stumped here
If anyone can point me to some guideline or sample code on how these conflicts should be generally handled using information from the MobileServiceTableOperationError, that will be highly appreciated
I came across the following code snippet from the following doc.
// Simple error/conflict handling.
if (syncErrors != null)
{
foreach (var error in syncErrors)
{
if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null)
{
//Update failed, reverting to server's copy.
await error.CancelAndUpdateItemAsync(error.Result);
}
else
{
// Discard local change.
await error.CancelAndDiscardItemAsync();
}
Debug.WriteLine(#"Error executing sync operation. Item: {0} ({1}). Operation discarded.",
error.TableName, error.Item["id"]);
}
}
Surfacing conflicts to the UI I found in this doc
private async Task ResolveConflict(TodoItem localItem, TodoItem serverItem)
{
//Ask user to choose the resolution between versions
MessageDialog msgDialog = new MessageDialog(
String.Format("Server Text: \"{0}\" \nLocal Text: \"{1}\"\n",
serverItem.Text, localItem.Text),
"CONFLICT DETECTED - Select a resolution:");
UICommand localBtn = new UICommand("Commit Local Text");
UICommand ServerBtn = new UICommand("Leave Server Text");
msgDialog.Commands.Add(localBtn);
msgDialog.Commands.Add(ServerBtn);
localBtn.Invoked = async (IUICommand command) =>
{
// To resolve the conflict, update the version of the item being committed. Otherwise, you will keep
// catching a MobileServicePreConditionFailedException.
localItem.Version = serverItem.Version;
// Updating recursively here just in case another change happened while the user was making a decision
UpdateToDoItem(localItem);
};
ServerBtn.Invoked = async (IUICommand command) =>
{
RefreshTodoItems();
};
await msgDialog.ShowAsync();
}
I hope this helps provide some direction. Although the Azure Mobile docs have been deprecated, the SDK hasn't changed and should still be relevant. If this doesn't help, let me know what you're using for a backend store.

Vertx CompositeFuture

I am working on a solution where I am using vertx 3.8.4 and vertx-mysql-client 3.9.0 for asynchronous database calls.
Here is the scenario that I have been trying to resolve, in a proper reactive manner.
I have some mastertable records which are in inactive state.
I run a query and get the list of records from the database.
This I did like this :
Future<List<Master>> locationMasters = getInactiveMasterTableRecords ();
locationMasters.onSuccess (locationMasterList -> {
if (locationMasterList.size () > 0) {
uploadTargetingDataForAllInactiveLocations(vertx, amazonS3Utility,
locationMasterList);
}
});
Now in uploadTargetingDataForAllInactiveLocations method, i have a list of items.
What I have to do is, I need to iterate over this list, for each item, I need to download a file from aws, parse the file and insert those data to db.
I understand the way to do it using CompositeFuture.
Can someone from vertx dev community help me with this or with some documentation available ?
I did not find good contents on this by googling.
I'm answering this as I was searching for something similar and I ended up spending some time before finding an answer and hopefully this might be useful to someone else in future.
I believe you want to use CompositeFuture in vertx only if you want to synchronize multiple actions. That means that you either want an action to execute in the case that either all your other actions on which your composite future is built upon succeed or at least one of the action on which your composite future is built upon succeed.
In the first case I would use CompositeFuture.all(List<Future> futures) and in the second case I would use CompositeFuture.any(List<Future> futures).
As per your question, below is a sample code where a list of item, for each item we run an asynchronous operation (namely downloadAnProcessFile()) which returns a Future and we want to execute an action doAction() in the case that all the async actions succeeded:
List<Future> futures = new ArrayList<>();
locationMasterList.forEach(elem -> {
Promise<Void> promise = Promise.promise();
futures.add(promise.future());
Future<Boolean> processStatus = downloadAndProcessFile(); // doesn't need to be boolean
processStatus.onComplete(asyncProcessStatus -> {
if (asyncProcessStatus.succeeded()){
// eventually do stuff with the result
promise.complete();
} else {
promise.fail("Error while processing file whatever");
}
});
});
CompositeFuture.all(futures).onComplete(compositeAsync -> {
if (compositeAsync.succeeded()){
doAction(); // <-- here do what you want to do when all future complete
} else {
// at least 1 future failed
}
});
This solution is probably not perfect and I suppose can be improved but this is what I found works for me. Hopefully will work for someone else.

Parallel.Foreach and BulkCopy

I have a C# library which connects to 59 servers of the same database structure and imports data to my local db to the same table. At this moment I am retrieving data server by server in foreach loop:
foreach (var systemDto in systems)
{
var sourceConnectionString = _systemService.GetConnectionStringAsync(systemDto.Ip).Result;
var dbConnectionFactory = new DbConnectionFactory(sourceConnectionString,
"System.Data.SqlClient");
var dbContext = new DbContext(dbConnectionFactory);
var storageRepository = new StorageRepository(dbContext);
var usedStorage = storageRepository.GetUsedStorageForCurrentMonth();
var dtUsedStorage = new DataTable();
dtUsedStorage.Load(usedStorage);
var dcIp = new DataColumn("IP", typeof(string)) {DefaultValue = systemDto.Ip};
var dcBatchDateTime = new DataColumn("BatchDateTime", typeof(string))
{
DefaultValue = batchDateTime
};
dtUsedStorage.Columns.Add(dcIp);
dtUsedStorage.Columns.Add(dcBatchDateTime);
using (var blkCopy = new SqlBulkCopy(destinationConnectionString))
{
blkCopy.DestinationTableName = "dbo.tbl";
blkCopy.WriteToServer(dtUsedStorage);
}
}
Because there are many systems to retrieve data, I wonder if it is possible to use Pararel.Foreach loop? Will BulkCopy lock the table during WriteToServer and next WriteToServer will wait until previous will complete?
-- EDIT 1
I've changed Foreach to Parallel.Foreach but I face one problem. Inside this loop I have async method: _systemService.GetConnectionStringAsync(systemDto.Ip)
and this line returns error:
System.NotSupportedException: A second operation started on this
context before a previous asynchronous operation completed. Use
'await' to ensure that any asynchronous operations have completed
before calling another method on this context. Any instance members
are not guaranteed to be thread safe.
Any ideas how can I handle this?
In general, it will get blocked and will wait until the previous operation complete.
There are some factors that may affect if SqlBulkCopy can be run in parallel or not.
I remember when adding the Parallel feature to my .NET Bulk Operations, I had hard time to make it work correctly in parallel but that worked well when the table has no index (which is likely never the case)
Even when worked, the performance gain was not a lot faster.
Perhaps you will find more information here: MSDN - Importing Data in Parallel with Table Level Locking

JOliver EventStore Snapshotting

Say I have this code:
private void CreateSnapshots(IEnumerable<StreamHead> streams)
{
foreach (StreamHead head in streams)
{
IAggregate aggregate = ???;
IMemento memento = aggregate.GetSnapshot();
var snapshot = new Snapshot(head.StreamId, head.SnapshotRevision + 1, memento);
eventStore.AddSnapshot(snapshot);
observer.Notify(new SnapshotTaken(head.StreamId, head.HeadRevision));
}
}
how do I know what aggregate to load for the current stream? I'm also using CommonDomain. Is there something in there?
Thanks
The snapshotting aspect of the EventStore needs a bit of love. I have tried to make the IStoreEvents interface geared toward working with an individual aggregate. I have also tried to ensure that snapshotting does not interfere or get in the way of normal use.
Since the release of v2.0, I have now turned my attention toward v2.1 and I will be able to make a few small API changes related to this. In the meantime, your best option is probably to bypass IStoreEvents altogether when doing snapshotting.
Another alternative is to have the snapshotting code run in-process with your regular code. When an aggregate is loaded the needs a snapshot, you could easily push a reference to that aggregate asynchronously to your snapshotting code. In this way, you don't actually have to do a load because you already have the aggregate.
I found a solution for me (this is most definitely a hack). It is still out-of-band snapshotting. Here's a sample of it in action.
private void CreateSnapshots(IEnumerable<StreamHead> streams)
{
foreach (StreamHead head in streams)
{
//NOTE: This uses a patched version of EventStore that loads commit headers in OptimisticEventStream.PopulateStream()
// <code>
// this.identifiers.Add(commit.CommitId);
// this.headers = this.headers.Union(commit.Headers).ToDictionary(k => k.Key, k => k.Value);
// </code>
var stream = eventStore.OpenStream(head.StreamId, int.MinValue, int.MaxValue);
//NOTE: Nasty hack but it works.
var aggregateType = stream.UncommittedHeaders.Where(p=>p.Key=="AggregateType").First();
var type = aggregateTypeResolver(aggregateType.Value.ToString());
MethodInfo methodInfo = typeof(IRepository).GetMethod("GetById");
MethodInfo method = methodInfo.MakeGenericMethod(type);
object o = method.Invoke(repository, new object[]{head.StreamId, head.HeadRevision});
var aggregate = (IAggregate) o;
IMemento memento = aggregate.GetSnapshot();
var snapshot = new Snapshot(head.StreamId, head.HeadRevision, memento);
eventStore.AddSnapshot(snapshot);
observer.Notify(new SnapshotTaken(head.StreamId, head.HeadRevision));
}
}