I'm still using OpenRiaServices and I update to version 5.0.0-preview0003.
I tried to add an async method :
[Invoke]
[RequiresAuthentication]
public async Task<string> GetTestAsync()
{
return await Task.FromResult("TEST");
}
But when I'm calling it, the method never returns :
var test = DomainContext.GetTestAsync(CancellationToken.None).Result;
I see that there is no "await" in the generated code :
/// <summary>
/// Asynchronously invokes the 'GetTest' method of the DomainService.
/// </summary>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the work</param>
/// <returns>An operation instance that can be used to manage the asynchronous request.</returns>
[DebuggerStepThrough()]
public System.Threading.Tasks.Task<InvokeResult<string>> GetTestAsync(CancellationToken cancellationToken = default(CancellationToken))
{
this.ValidateMethod("GetTest", null);
return this.InvokeOperationAsync<string>("GetTest", null, true, cancellationToken);
}
I tried to debug it but I don't know where the problem happens...
Any idea why ?
The issue has been answered over [at the OpenRiaServices Github)(https://github.com/OpenRIAServices/OpenRiaServices/issues/246)
The issue was a deadlock due to calling Task.Result instead of awaiting the result
Related
I have a CQRS setup and I am trying to use domain events.
After I receive a command for a new order, I am adding the newly created Order object to the dbcontext.
public async Task<Guid> Handle(CreateOrderCommand message, CancellationToken cancellationToken)
{
...
var order = new Order(...);
...
order.SubmitOrder();
_orderRepository.Add(order);
await _orderRepository.UnitOfWork
.SaveEntitiesAsync(cancellationToken);
return order.Id;
}
The order.SubmitOrder() method is as follows
public void SubmitOrder()
{
AddDomainEvent(new OrderPlacedDomainEvent(Guid.NewGuid(), Id));
}
and orderRepository.UnitOfWork.SaveEntitiesAsync(cancellationToken); is on overload to the UnitOfWork.SaveEntitiesAsync() as follows:
public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default)
{
// Dispatch Domain Events collection.
// Choices:
// A) Right BEFORE committing data (EF SaveChanges) into the DB will make a single transaction including
// side effects from the domain event handlers which are using the same DbContext with "InstancePerLifetimeScope" or "scoped" lifetime
// B) Right AFTER committing data (EF SaveChanges) into the DB will make multiple transactions.
// You will need to handle eventual consistency and compensatory actions in case of failures in any of the Handlers.
if (_mediator != null)
{
await _mediator.DispatchDomainEventsAsync(this);
}
// After executing this line all the changes (from the Command Handler and Domain Event Handlers)
// performed through the DbContext will be committed
await base.SaveChangesAsync(cancellationToken);
return true;
}
Note that the changes are not saved before the events are dispatched and the handler is called.
Now in the event handler when I am trying to get the order object from the context:
await _context.Orders.Include(o => o.OrderItems).SingleOrDefaultAsync(o => o.Id == id, cancellationToken: cancellationToken);
it returns null although the data is available in the context under _context.ChangeTracker.DebugView.LongView
Is there any way to get the order data here?
Well, solution found:
If Find/FindAsyncis used instead of SingleOrDefaultAsync it will return the values available in the change tracker.
public async Task<Order?> FindAsync(Guid id, CancellationToken cancellationToken = default)
=> await _context.Orders.FindAsync(new object[] { id }, cancellationToken: cancellationToken);
I want to batch many futures into a single request that triggers either when a maximum batch size is reached, or a maximum time since the earliest future was received is reached.
Motivation
In flutter, I have many UI elements which need to display the result of a future, dependent on the data in the UI element.
For instance, I have a widget for a place, and a sub-widget which displays how long it will take to walk to a place. To compute the how long it will take to walk, I issue a request to Google Maps API to get the travel time to the place.
It is more efficient and cost-effective to batch all these API requests into a batch API request. So if there are 100 requests made instantaneously by the widgets, then the futures could be proxied through a single provider, which batches the futures into a single request to Google, and unpacks the result from Google into all the individual requests.
The provider needs to know when to stop waiting for more futures and when to actually issue the request, which should be controllable by the maximum "batch" size (i.e., # of travel time requests), or the maximum amount of time you are willing to wait for batching to take place.
The desired API would be something like:
// Client gives this to tell provider how to compute batch result.
abstract class BatchComputer<K,V> {
Future<List<V>> compute(List<K> batchedInputs);
}
// Batching library returns an object with this interface
// so that client can submit inputs to completed by the Batch provider.
abstract class BatchingFutureProvider<K,V> {
Future<V> submit(K inputValue);
}
// How do you implement this in dart???
BatchingFutureProvider<K,V> create<K,V>(
BatchComputer<K,V> computer,
int maxBatchSize,
Duration maxWaitDuration,
);
Does Dart (or a pub package) already provide this batching functionality, and if not, how would you implement the create function above?
This sounds perfectly reasonable, but also very specialized.
You need a way to represent a query, to combine these queries into a single super-query, and to split the super-result into individual results afterwards, which is what your BatchComputer does. Then you need a queue which you can flush through that under some conditions.
One thing that is clear is that you will need to use Completers for the results because you always need that when you want to return a future before you have the value or future to complete it with.
The approach I would choose would be:
import "dart:async";
/// A batch of requests to be handled together.
///
/// Collects [Request]s until the pending requests are flushed.
/// Requests can be flushed by calling [flush] or by configuring
/// the batch to automatically flush when reaching certain
/// tresholds.
class BatchRequest<Request, Response> {
final int _maxRequests;
final Duration _maxDelay;
final Future<List<Response>> Function(List<Request>) _compute;
Timer _timeout;
List<Request> _pendingRequests;
List<Completer<Response>> _responseCompleters;
/// Creates a batcher of [Request]s.
///
/// Batches requests until calling [flush]. At that pont, the
/// [batchCompute] function gets the list of pending requests,
/// and it should respond with a list of [Response]s.
/// The response to the a request in the argument list
/// should be at the same index in the response list,
/// and as such, the response list must have the same number
/// of responses as there were requests.
///
/// If [maxRequestsPerBatch] is supplied, requests are automatically
/// flushed whenever there are that many requests pending.
///
/// If [maxDelay] is supplied, requests are automatically flushed
/// when the oldest request has been pending for that long.
/// As such, The [maxDelay] is not the maximal time before a request
/// is answered, just how long sending the request may be delayed.
BatchRequest(Future<List<Response>> Function(List<Request>) batchCompute,
{int maxRequestsPerBatch, Duration maxDelay})
: _compute = batchCompute,
_maxRequests = maxRequestsPerBatch,
_maxDelay = maxDelay;
/// Add a request to the batch.
///
/// The request is stored until the requests are flushed,
/// then the returned future is completed with the result (or error)
/// received from handling the requests.
Future<Response> addRequest(Request request) {
var completer = Completer<Response>();
(_pendingRequests ??= []).add(request);
(_responseCompleters ??= []).add(completer);
if (_pendingRequests.length == _maxRequests) {
_flush();
} else if (_timeout == null && _maxDelay != null) {
_timeout = Timer(_maxDelay, _flush);
}
return completer.future;
}
/// Flush any pending requests immediately.
void flush() {
_flush();
}
void _flush() {
if (_pendingRequests == null) {
assert(_timeout == null);
assert(_responseCompleters == null);
return;
}
if (_timeout != null) {
_timeout.cancel();
_timeout = null;
}
var requests = _pendingRequests;
var completers = _responseCompleters;
_pendingRequests = null;
_responseCompleters = null;
_compute(requests).then((List<Response> results) {
if (results.length != completers.length) {
throw StateError("Wrong number of results. "
"Expected ${completers.length}, got ${results.length}");
}
for (int i = 0; i < results.length; i++) {
completers[i].complete(results[i]);
}
}).catchError((error, stack) {
for (var completer in completers) {
completer.completeError(error, stack);
}
});
}
}
You can use that as, for example:
void main() async {
var b = BatchRequest<int, int>(_compute,
maxRequestsPerBatch: 5, maxDelay: Duration(seconds: 1));
var sw = Stopwatch()..start();
for (int i = 0; i < 8; i++) {
b.addRequest(i).then((r) {
print("${sw.elapsedMilliseconds.toString().padLeft(4)}: $i -> $r");
});
}
}
Future<List<int>> _compute(List<int> args) =>
Future.value([for (var x in args) x + 1]);
See https://pub.dev/packages/batching_future/versions/0.0.2
I have almost exactly the same answer as #lrn, but have put some effort to make the main-line synchronous, and added some documentation.
/// Exposes [createBatcher] which batches computation requests until either
/// a max batch size or max wait duration is reached.
///
import 'dart:async';
import 'dart:collection';
import 'package:quiver/iterables.dart';
import 'package:synchronized/synchronized.dart';
/// Converts input type [K] to output type [V] for every item in
/// [batchedInputs]. There must be exactly one item in output list for every
/// item in input list, and assumes that input[i] => output[i].
abstract class BatchComputer<K, V> {
const BatchComputer();
Future<List<V>> compute(List<K> batchedInputs);
}
/// Interface to submit (possible) batched computation requests.
abstract class BatchingFutureProvider<K, V> {
Future<V> submit(K inputValue);
}
/// Returns a batcher which computes transformations in batch using [computer].
/// The batcher will wait to compute until [maxWaitDuration] is reached since
/// the first item in the current batch is received, or [maxBatchSize] items
/// are in the current batch, whatever happens first.
/// If [maxBatchSize] or [maxWaitDuration] is null, then the triggering
/// condition is ignored, but at least one condition must be supplied.
///
/// Warning: If [maxWaitDuration] is not supplied, then it is possible that
/// a partial batch will never finish computing.
BatchingFutureProvider<K, V> createBatcher<K, V>(BatchComputer<K, V> computer,
{int maxBatchSize, Duration maxWaitDuration}) {
if (!((maxBatchSize != null || maxWaitDuration != null) &&
(maxWaitDuration == null || maxWaitDuration.inMilliseconds > 0) &&
(maxBatchSize == null || maxBatchSize > 0))) {
throw ArgumentError(
"At least one of {maxBatchSize, maxWaitDuration} must be specified and be positive values");
}
return _Impl(computer, maxBatchSize, maxWaitDuration);
}
// Holds the input value and the future to complete it.
class _Payload<K, V> {
final K k;
final Completer<V> completer;
_Payload(this.k, this.completer);
}
enum _ExecuteCommand { EXECUTE }
/// Implements [createBatcher].
class _Impl<K, V> implements BatchingFutureProvider<K, V> {
/// Queues computation requests.
final controller = StreamController<dynamic>();
/// Queues the input values with their futures to complete.
final queue = Queue<_Payload>();
/// Locks access to [listen] to make queue-processing single-threaded.
final lock = Lock();
/// [maxWaitDuration] timer, as a stored reference to cancel early if needed.
Timer timer;
/// Performs the input->output batch transformation.
final BatchComputer computer;
/// See [createBatcher].
final int maxBatchSize;
/// See [createBatcher].
final Duration maxWaitDuration;
_Impl(this.computer, this.maxBatchSize, this.maxWaitDuration) {
controller.stream.listen(listen);
}
void dispose() {
controller.close();
}
#override
Future<V> submit(K inputValue) {
final completer = Completer<V>();
controller.add(_Payload(inputValue, completer));
return completer.future;
}
// Synchronous event-processing logic.
void listen(dynamic event) async {
await lock.synchronized(() {
if (event.runtimeType == _ExecuteCommand) {
if (timer?.isActive ?? true) {
// The timer got reset, so ignore this old request.
// The current timer needs to inactive and non-null
// for the execution to be legitimate.
return;
}
execute();
} else {
addPayload(event as _Payload);
}
return;
});
}
void addPayload(_Payload _payload) {
if (queue.isEmpty && maxWaitDuration != null) {
// This is the first item of the batch.
// Trigger the timer so we are guaranteed to start computing
// this batch before [maxWaitDuration].
timer = Timer(maxWaitDuration, triggerTimer);
}
queue.add(_payload);
if (maxBatchSize != null && queue.length >= maxBatchSize) {
execute();
return;
}
}
void execute() async {
timer?.cancel();
if (queue.isEmpty) {
return;
}
final results = await computer.compute(List<K>.of(queue.map((p) => p.k)));
for (var pair in zip<Object>([queue, results])) {
(pair[0] as _Payload).completer.complete(pair[1] as V);
}
queue.clear();
}
void triggerTimer() {
listen(_ExecuteCommand.EXECUTE);
}
}
Is there a method or strategy to understand when ProcessPurchase was called from a restore item?
I'm looking both for iOs and Google
Is here:
https://docs.unity3d.com/Manual/UnityIAPRestoringTransactions.html
/// <summary>
/// Your IStoreListener implementation of OnInitialized.
/// </summary>
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
extensions.GetExtension<IAppleExtensions> ().RestoreTransactions (result => {
if (result) {
// This does not mean anything was restored,
// merely that the restoration process succeeded.
} else {
// Restoration failed.
}
});
}
I hope this could help: https://unity3d.com/cn/learn/tutorials/topics/analytics/integrating-unity-iap-your-game
relevant code is, which is from the code sample:
public void BuyNonConsumable()
{
// Buy the non-consumable product using its general identifier. Expect a response either
// through ProcessPurchase or OnPurchaseFailed asynchronously.
BuyProductID(kProductIDNonConsumable);
}
What am I missing?
I'm trying to read with NOLOCK using a TransactionScope like this:
var scopeOptions = new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted };
using (var scope = new TransactionScope(TransactionScopeOption.Required, scopeOptions))
{
using (var db = new MyDbContext(ConnectionStringEntities))
{
// Simple read with a try catch block...
}
scope.Complete();
}
I expected to see with NOLOCK added to the SQL query (looking in SQL Profiler and also a custom DbCommandInterceptor - but it's not there...
UPDATE: after some more research, I wonder if the selected cursor is being used after all, just without the NOLOCK "hint" (SQL Server specific - and also specific to just one table), I found some code that get the current transaction and it seem to show the right selected transaction isolation (ReadUncommitted / Serializable etc.)I still want to test it but let me know if you have any thoughts
Get current .net TransactionScope IsolationLevel
Transaction trans = Transaction.Current;
System.Transactions.IsolationLevel level = trans.IsolationLevel;
LogService.Instance.Debug($"Transaction IsolationLevel = {level.ToString()}");
So it looks like Entity Framework does respect the IsolationLevel, only it does not use the NOLOCK hint (probably because it is too database specific) and this by the way my main complaint against EF - that it is not very optimized for different database types, another example is where the new identity is saving a GUID primary key for AspNetUsers as a string (again for lack of optimization) other than that (and few other things) EF is awesome!
I could not find a solution to my problem anywhere, I definitely didn't want to make all my queries use NOLOCK - just the uncommitted ones, so I ended up combining two solutions (with some changes):
NoLockInterceptor - for adding NOLOCK on the fly (Entity Framework with NOLOCK):
/// <summary>
/// Add "WITH (NOLOCK)" hint to SQL queries, SQL Server specifc - may break queries on different databases.
/// (conditionally turn off with NoLockInterceptor.AddNoLockHintToSqlQueries = false to change on runtime)
/// <para>
/// https://stackoverflow.com/questions/926656/entity-framework-with-nolock
/// </para>
/// </summary>
public class NoLockInterceptor : DbCommandInterceptor
{
private static readonly Regex TableAliasRegex = new Regex(
#"(?<tableAlias>AS \[Extent\d+\](?! WITH \(NOLOCK\)))",
RegexOptions.Multiline | RegexOptions.IgnoreCase);
/// <summary>
/// Add "WITH (NOLOCK)" hint to SQL queries - unique to each thread
/// (set to true only when needed and then back to false)
/// </summary>
[ThreadStatic]
public static bool AddNoLockHintToSqlQueries;
public NoLockInterceptor()
{
// Do not use by default for all queries
AddNoLockHintToSqlQueries = false;
}
public override void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
if (AddNoLockHintToSqlQueries)
{
command.CommandText = TableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)");
}
}
public override void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
if (AddNoLockHintToSqlQueries)
{
command.CommandText = TableAliasRegex.Replace(command.CommandText, "${tableAlias} WITH (NOLOCK)");
}
}
}
TransactionWrapper - to invoke the NoLockInterceptor behaviour and also useful for repeated use of transactions (http://haacked.com/archive/2009/08/18/simpler-transactions.aspx/):
/// <summary>
/// Transaction wrapper for setting pre-defined transaction scopes
/// <para>
/// http://haacked.com/archive/2009/08/18/simpler-transactions.aspx/
/// </para>
/// </summary>
public static class TransactionWrapper
{
/// <summary>
/// Set transaction scope and using NoLockInterceptor for adding SQL Server specific "WITH (NOLOCK)"
/// to ReadUncommitted isolation level transactions (not supported by Entity Framework)
/// </summary>
/// <param name="isolationLevel"></param>
/// <param name="transactionScopeOption"></param>
/// <param name="timeout"></param>
/// <param name="action"></param>
public static void SetScope(IsolationLevel isolationLevel, TransactionScopeOption transactionScopeOption,
TimeSpan timeout, Action action)
{
var transactionOptions = new TransactionOptions { IsolationLevel = isolationLevel, Timeout = timeout };
using (var transactionScope = new TransactionScope(transactionScopeOption, transactionOptions))
{
if (isolationLevel == IsolationLevel.ReadUncommitted)
NoLockInterceptor.AddNoLockHintToSqlQueries = true;
action();
transactionScope.Complete();
if (isolationLevel == IsolationLevel.ReadUncommitted)
NoLockInterceptor.AddNoLockHintToSqlQueries = false;
}
}
}
Use it like this:
var timeout = TimeSpan.FromSeconds(ConfigVariables.Instance.Timeout_Transaction_Default_In_Seconds);
TransactionWrapper.SetScope(IsolationLevel.ReadUncommitted, TransactionScopeOption.Required, timeout, () =>
{
using (var db = new MyDbContext(MyDbContextConnectionStringEntities))
{
// Do stuff...
}
});
NOLOCK is now added just to queries with a ReadUncommitted transaction isolation level scopes.
You can't get Entity Framework to render the NOLOCK hint. If you want to read un-committed data, you have to do something different like what you did by adding the TransactionScope with IsolationLevel.ReadUncommited to the TransactionOptions.
Writing your own command interceptor or your own EF provider would also work.
https://msdn.microsoft.com/en-us/data/dn469464.aspx
I've tried transaction scope and it then profile the calls to the DB. EF begins and ends the transaction but never changes the isolation level from Read Committed.
using (var scope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions()
{
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
}))
{
List<T> toReturn = query.ToList();
scope.Complete();
return toReturn;
}
In my app, I need a one off timer that'll perform an action and never be used again. I've been cracking down on performance lately and was wondering what the correct way to do this would be.
If I do the following:
NSTimer.CreateScheduledTimer(10, delegate {
Console.WriteLine("Timer fired!");
// other non-trivial code here
});
Once this has fired, is this going to be automagically cleaned up by Mono's GC? Or would it be better to create a reference to this timer (NSTimer timer = NSTimer.CreateScheduledTimer()) and then dispose of it myself?
Does this apply to other objects which can be instantiated in a similar manner?
Your sample code is probably the way to go. GC will clean up sometime after the timer has fired. The only reason you might want to hold a reference to the timer is if you'd want to cancel the timer at some point.
I use this little helper. Good thing is that it can be used in all NSObject derived classes and helps when converting code from ObjC as it is pretty much the same call.
namespace MonoTouch.Foundation.Extensions
{
public static class CoreFoundationExtensions
{
/// <summary>
/// Performs the selector.
/// </summary>
/// <param name='obj'>
/// Object.
/// </param>
/// <param name='action'>
/// Action.
/// </param>
/// <param name='delay'>
/// Delay.
/// </param>
public static void PerformSelector (this NSObject obj, NSAction action, float delay)
{
int d = (int)(1000 * delay);
var thread = new Thread(new ThreadStart ( () => {
using(var pool = new NSAutoreleasePool())
{
Thread.Sleep (d);
action.Invoke ();
}
}));
thread.IsBackground = true;
thread.Start();
}
/// <summary>
/// Performs the selector.
/// </summary>
/// <param name='obj'>
/// Object.
/// </param>
/// <param name='action'>
/// Action.
/// </param>
public static void PerformSelector (this NSObject obj, NSAction action)
{
PerformSelector (obj, action, 0.001f);
}
}
}