How to use $transaction API in this scenario? - prisma

const a = prisma.user.create()
throw new Error() // some error happened
const b = prisma.user.create()
prisma.$transaction([a, b])
Since an error happened, prisma.$transaction was never called, so a inserted into the database.

a will never be inserted into the database as the prisma.user.create() command will only be called inside prisma.$transaction so you do not need to check for that.

How about
const [a, b] = await prisma.$transaction([prisma.user.create(), prisma.user.create()])

Related

Awaiting the same method (passed as a parameter) twice

I'm trying to write a method inside a package I'm currently developing but I got stuck trying to await the same method a second time.
This is the pseudo code for my method:
Future<MyResultClass> ErrorHandlingMethod(Future<MyResultClass> MyMethod) async {
MyResultClass result = await MyMethod;
(if result.failed && result.cause.canBeFixed){
...
...
// Do something that may cause MyMethod to complete successfully
...
...
result = await MyMethod;
}
return result;
}
MyMethod (a DIO request with a bunch of interceptors) completes but the server returns an error code, now in some cases I can fix whatever caused the problem so after doing that I want to make the same call again and return the new result.
The problem is the second time I'm awaiting MyMethod it returns the result I got the first time without making a new DIO request.
The real code is a little more complicated than this but this is the main problem I'm having right now.
Does anyone know how can I force MyMethod to be actually executed again?
Thanks in advance for your help

What impact does changing a IReliableQueue to a IReliableConcurrentQueue have in an existing deployment?

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.

How to fake throwing an exception?

I have following setup
A.CallTo(() => fakeChargeService
.CreateAsync(A<ChargeCreateOptions>._, A<RequestOptions>._, A<CancellationToken>._))
.Throws<StripeException>((se) => stripeException);
and then I assert
var msg = await Assert.ThrowsAsync<StripeException>(async () => await mediator.Send(command, CancellationToken.None));
which eventually executes this piece of code
var policyResult = await Policy.Handle<StripeException>(x => x.ShouldRetry())
.WaitAndRetryAsync(new[]
{
TimeSpan.FromSeconds(0.5),
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2),
})
.ExecuteAndCaptureAsync(async () => await this.chargeService.CreateAsync(options, null, cancellationToken));
and here I get error
Assert.Throws() Failure
Expected: typeof(Stripe.StripeException)
Actual: typeof(FakeItEasy.Configuration.FakeConfigurationException): The faked method has the signature (Stripe.ChargeCreateOptions, Stripe.RequestOptions, System.Threading.CancellationToken), but throws was used with (Stripe.StripeException).
I am not sure what is it that I am doing wrong. Any help would be appreciated
You seem to be specifying the wrong signature in your Throws. CreateAsync takes (Stripe.ChargeCreateOptions, Stripe.RequestOptions, System.Threading.CancellationToken), but Throws was used with (Stripe.StripeException).
See the second example in Throwing Exceptions:
// Pass up to 4 original call argument values into the method that creates the exception.
A.CallTo(() => fakeShop.NumberOfSweetsSoldOn(A<DateTime>._))
.Throws((DateTime when)=>new InvalidDateException(when + " is in the future"));
Note that the signature of the lambda and the called method match.
You should update your lambda to match the proper signature. Or better yet, just replace with
.Throws<StripeException>(stripeException)
since there doesn't appear to be any reason to lazily throw, based on the snippet of code you provided.

#ngrx Effect does not run the second time

I've just started learning about #ngrx/store and #ngrx.effects and have created my first effect in my Angular/Ionic app. It runs ok the first time but if I dispatch the event to the store again (i.e when clicking the button again), nothing happens (no network call is made, nothing in console logs). Is there something obvious I'm doing wrong? Here's the effect:
#Effect() event_response$ = this.action$
.ofType(SEND_EVENT_RESPONSE_ACTION)
.map(toPayload)
.switchMap((payload) => this.myService.eventResponse(payload.eventId,payload.response))
.map(data => new SentEventResponseAction(data))
.catch((error) => Observable.of(new ErrorOccurredAction(error)));
Thanks
It sounds like an error is occurring. In that situation, the action in the observable returned by catch will be emitted into the effect's stream and the effect will then complete - which will prevent the effect from running after the error action is emitted.
Move the map and the catch into the switchMap:
#Effect() event_response$ = this.action$
.ofType(SEND_EVENT_RESPONSE_ACTION)
.map(toPayload)
.switchMap((payload) => this.myService
.eventResponse(payload.eventId, payload.response)
.map(data => new SentEventResponseAction(data))
.catch((error) => Observable.of(new ErrorOccurredAction(error)))
);
Composing the catch within the switchMap will prevent the effect from completing if an error occurs.
You must move map() and catchError() into swithchMap() as following
#Effect()
public event_response$ = this.action$.pipe(
ofType(SEND_EVENT_RESPONSE_ACTION),
switchMap((payload) => {
return this.myService.eventResponse(payload.eventId,payload.response).pipe(
map((data: DataType) => new SentEventResponseAction(data)),
catchError((error) => Observable.of(new ErrorOccurredAction(error)))
})
);
);
Please note that, evetResponse() method inside myService should return an observable in order to use pipe afterward.
In case your method inside service returns Promise, you can convert it into an observable by the use of from in the rxjs package as below:
import { from } from 'rxjs';
...
const promise = this.myService.eventResponse(payload.eventId,payload.response);
const observable = from(promise);
return observable.pipe(...
For more and detail description take a look at this link

Angular 2 - Two Services, second requires result of first

I guess I need some type of promise chain, but the syntax eludes me...
Within the same component:
I'm calling:
this.somethingService.getSomethings().then(somethings => this.somethings = somethings);
Then I need to call:
this.otherService.getOthers(this.somethings).then(others => this.others = others);
In the second service call I'm using the result of the first to perform aggregate functions on its content, but its empty when the second call is made, thus the second service returns empty.
How can I get the second service to wait until the first promise has been resolved.
Thanx
Steve
You can chain promises this way:
this.somethingService.getSomethings().then(somethings => {
this.somethings = somethings;
return this.otherService.getOthers(somethings);
}).then(others => {
this.others = others;
});
The second callback will receive the result of the promise returns by the first callback.