FirstOrDefaultAsync() Hangs MVC5 - entity-framework

Someone please help me not kill my Server.. Here's my MVC controller action:
(Don't worry about names, I'm mid-refactoring)
public async Task<ActionResult> AllByLead(int leadId)
{
try
{
var lead = await _researchService.GetLeadWithContacts(leadId);
var contactViewModels = Mapper.Map<Lead, List<ContactViewModel>>(lead);
contactViewModels.Each(contact => PopulateContactOptions(contact));
var listViewModel = new ContactListViewModel {Results = contactViewModels};
return PartialView(listViewModel);
}
catch
{
return Json(string.Format(Resources.BasicErrorMessageFormat, "Error retrieving Lead Contacts"),
JsonRequestBehavior.AllowGet);
}
}
Service:
public async Task<Lead> GetLeadWithContacts(int leadId)
{
return await _repository.GetLeadWithContacts(leadId).ConfigureAwait(false);
}
Repo:
public async Task<Lead> GetLeadWithContacts(int leadId)
{
var leadEntity = await _context.Leads
.Where(lead => lead.LeadID == leadId)
//.Include(lead => lead.LeadContactMaps.Select(map => map.Contact.Addresses))
//.Include(lead => lead.LeadContactMaps.Select(map => map.Contact.PhoneNumbers))
//.Include(lead => lead.Organizations.Select(business => business.Addresses))
//.Include(lead => lead.Organizations.Select(business => business.PhoneNumbers))
.FirstOrDefaultAsync();
return leadEntity;
}
EDIT
DbContext Module
internal class DbContextModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(ctx => new CRTechEntities()).InstancePerLifetimeScope();
}
}
JS Ajax Call:
function populateContactList() {
var leadId = $("#LeadId").val();
$.ajax({
url: url + "/Contact/AllByLead/",
type: "GET",
data: { 'leadId': leadId },
success: function(data) {
$("#contactContainer").html(data);
},
error: function(data) {
}
});
}
Bonus points on if you can school me on my includes, they may very well be terrible.. It's pretty slow just grabbing the lead right now. Hence the async change. I'd like to see if it will be easier on the system with more users. (I can do my own profiling/tests on whether explicit loading will be better here, just saying..)
Anyway, I hit this, the server is completely borked when the await FirstOrDefaultAsync() gets hit.
EDIT 2: I've updated the controller action to show exactly what I'm doing here. I only included the code that was being hit originally.

Um, are you returning anything in your controller? That would cause it to hang.
Try
public async Task<JsonResult> AllByLead(int leadId)
{
var lead = await _researchService.GetLeadWithContacts(leadId);
return Json(lead);
}

Related

how to guarantee responses are processed in the same order as requests

In response to a click handler, i currently perform a:
axios.get("http://whatever.com/itemId").then(response => {
console.log(response);
});
theoretically, a user might click several times extremely quickly in succession. however, I need to process responses in the same order as the requests are made, and these responses are not always ordered.
Can anyone give any pointers?
Came up with the following, which seems to work well. Maybe such a thing should be part of the library itself. Hope others find it useful.
import axios from 'axios';
class OrderedAxios {
constructor() {
this.promises = []
}
get(url) {
var outsideResolve;
var outsideReject;
let promise = new Promise((resolve, reject) => {
outsideResolve = resolve;
outsideReject = reject;
});
promise.resolve = outsideResolve;
promise.reject = outsideReject;
this.promises.push(promise);
axios.get(url)
.then(response => {
promise.response = response;
this.processPromises();
})
.catch(error => {
promise.error = error;
this.processPromises();
})
return promise;
}
processPromises() {
let continueProcessing = false;
do {
continueProcessing = false;
if (this.promises.length) {
let promise = this.promises[0];
if (promise.response || promise.error) {
this.promises.shift();
if (promise.response) {
promise.resolve(promise.response);
} else {
promise.reject(promise.error);
}
continueProcessing = true;
}
}
} while (continueProcessing);
}
}
export default OrderedAxios;

Ionic Storage : Strange behavior?

I try to use the Ionic Storage module to store some values, for example my authentication token :
/**
* Get Token
*/
public get token(): string {
this.storage.get(this.LS_TOKEN).then((val) => {
console.log(val);
this._token.next(val);
console.log( this._token.getValue());
});
return this._token.getValue();
// return 'testtttt';
}
I try multiple things, return directly the value, set the value and return the variable...
But I always got a null, and the thing that is strange is that if I return a string directly it works, when I console.log the val it show the string that I want, but the return is always null..
What am I doing wrong ?
Edit :
In response of the first answer I have tried this :
/**
* Get Token
*/
public get token() {
this.tokenPromise().then(yourToken => {
console.log(yourToken);
return yourToken;
});
}
public tokenPromise() {
return new Promise((resolve, reject) => {
this.storage.get(this.LS_TOKEN).then((val) => {
resolve(val);
}).catch(ex => {
reject(ex);
});
});
}
My problem is the same, in my components when I try to use : console.log(this.sharedService.token);
It's still null
It is not working with your new token() method.
It is still asnychron. Im gonna show you:
public get token() {
return new Promise((resolve, reject)=>{
this.storage.get(this.LS_TOKEN).then((val) => {
resolve(val);
}).catch(ex=>{
reject(ex);
});
});
}
Now you can use your token from the sharedservice like this:
this.sharedService.token.then(token=>{
//use token here;
});
or you can use await, but the function who is calling it, must be async:
async useTokenFromService(){
let token = await this.sharedService.token;
console.log(token);
}
You are getting a Promise from the storage.get() method.
This means it is running asynchron.
You can return Promise.
public get token() {
return new Promise((resolve, reject)=>{
this.storage.get(this.LS_TOKEN).then((val) => {
resolve(val);
}).catch(ex=>{
reject(ex);
});
});
}
And you can receive this with an async function and await the result:
async loadToken(){
let loadedToken = await this.token();
// use your loadedToken here...
}
Or you can use the .then method from the promise like this:
loadToken(){
this.token().then(yourToken=>{
// use the token yourToken here...
});
}

Error: Nonce is too small - Bitfinex api

I try to call rest API from Bitfinex by using bitfinex library (https://www.npmjs.com/package/bitfinex). The documentation warned this error when running more than 1 process at the same time with the same API keys. However, I believe that I only run a process at once and even I generate new API keys, the error still happens. I'm thinking about overriding the nonce or extending it but I don't know how to do this. I haved tried some suggestions on the Internet, but still nothing worked.
Below is my code for reference:
import Bitfinex = require('bitfinex');
import pollingtoevent = require('polling-to-event');
import { Logger, LoggerFactory } from '../../common';
import { AppDataServices } from '../../data';
export class BitfinexPoller {
private static readonly LOGGER: Logger = LoggerFactory.getLogger();
private bitfinex: any = undefined;
private emitter: any = undefined;
private public_key: string = '<my-public-key>';
private secret_key: string = '<my-secret-key>';
private nonce: any = new Date().getTime();
constructor(private appServices: AppDataServices) {
BitfinexPoller.LOGGER.info('Bitfinex poller init');
this.bitfinex = new Bitfinex(this.public_key, this.secret_key, this.nonce);
// Lend book service
this.emitter = pollingtoevent((done: any) => {
this.bitfinex.lendbook('USD', (err: any, res: any, orderId: any) => {
done(err, res);
});
}, { interval: 30000, eventName: 'bitfinex-lending' });
this.emitter.on('bitfinex-lending', (data: any) => {
BitfinexPoller.LOGGER.info(data);
if (data.bids !== undefined) {
for (const row of data.bids) {
appServices.lendbookService.insert(BitfinexPoller.lendingData('BID', row));
}
}
if (data.asks !== undefined) {
for (const row of data.asks) {
appServices.lendbookService.insert(BitfinexPoller.lendingData('ASK', row));
}
}
});
// Order book service
this.emitter = pollingtoevent((done: any) => {
this.bitfinex.orderbook('btcusd', (err: any, res: any, orderId: any) => {
done(err, res);
});
}, { interval: 30000, eventName: 'bitfinex-order' });
this.emitter.on('bitfinex-order', (data: any) => {
BitfinexPoller.LOGGER.info(data);
if (data.bids !== undefined) {
for (const row of data.bids) {
appServices.lendbookService.insert(BitfinexPoller.orderData('BID', row));
}
}
if (data.asks !== undefined) {
for (const row of data.asks) {
appServices.lendbookService.insert(BitfinexPoller.orderData('ASK', row));
}
}
});
}
}
It's most likely you're firing off two authenticated calls in quick succession. The order that you send requests is not always the same as the order that they're processed, so the second request with the higher nonce is being processed first causing the first request to fail.
You can create and use multiple API keys for different requests or have a pool that you cycle through so you don't use the same api key multiple times in quick succession.
My solution with nodejs has been to defer the calls via promises.
Something like this:
function sleep(millis) {
return new Promise(resolve => setTimeout(resolve, millis));
}
sleep(500).then(() => {
//do work
});
sleep(600).then(() => {
//do work
});
Obviously if you are looking at extremely low latency and high speed this isn't for you.

Capture exception thrown in prototype (Typescript)

Excellent Angular 2/Material Design framework, Teradata Covalent, provides a RESTService abstract class that wraps REST api calls here:
https://teradata.github.io/covalent/#/components/http
Code to incorporate the extension is easy, as follows:
export class CustomRESTService extends RESTService<any> {
constructor(private _http: Http /* or HttpInterceptorService */) {
super(_http, {
baseUrl: 'www.api.com',
path: '/path/to/endpoint',
headers: new Headers(),
dynamicHeaders: () => new Headers(),
transform: (res: Response): any => res.json(),
});
}
}
The "update" method in the RESTService abstract class is shown here:
public update(id: string | number, obj: T, transform?: IRestTransform): Observable<any> {
let requestOptions: RequestOptionsArgs = this.buildRequestOptions();
let request: Observable<Response> = this.http.patch(this.buildUrl(id), obj, requestOptions);
return request.map((res: Response) => {
if (res.status === 200) {
if (transform) {
return transform(res);
}
return this.transform(res);
} else {
return res;
}
}).catch((error: Response) => {
return new Observable<any>((subscriber: Subscriber<any>) => {
try {
subscriber.error(this.transform(error));
} catch (err) {
subscriber.error(error);
}
});
});
}
My question is: if the update method of the abstract class throws an exception, how can that be captured in the CustomRESTService class? I.e., what Typescript code might one use to display an error in the UI?
Thank you.
First thing's first - Why would you want to catch it inside the rest client and not inside the app's logic?
Assuming you have some good reason for doing that (some other infrastructure code that you're running in the CustomRESTClient class), I would override the update function and implement error handling there.
A simple example without observables:
abstract class Base {
update(n:number):number {
return n;
}
test():bool;
}
class Child extends Base {
update(n:number):number {
return super.update(n)*2;
}
test():bool {
return true;
}
}

Debugging Ember-cli-mirage when routes are not being called

I have successfully created one route in ember-cli-mirage, but am having trouble loading the related data.
The API should be returning JSON API compliant data.
I'm not really sure if there are any good methods or not for debugging mirage's request interception. Here is my config.js
export default function() {
this.urlPrefix = 'https://myserver/';
this.namespace = 'api/v1';
this.get('/machines', function(db, request) {
return {
data: db.machines.map(attrs => (
{
type: 'machines',
id: attrs.id,
attributes: attrs
}
))
};
});
this.get('/machines/:id', function(db, request){
let id = request.params.id;
debugger;
return {
data: {
type: 'machines',
id: id,
attributes: db.machines.find(id),
relationships:{
"service-orders": db["service-orders"].where({machineId: id})
}
}
};
});
this.get('/machines/:machine_id/service-orders', function(db, request){
debugger; // this never gets caught
});
}
Most of this is working fine (I think). I can create machines and service orders in the factory and see the db object being updated. However, where my application would normally make a call to the api for service-orders: //myserver/machines/:machine_id/service-orders, the request is not caught and nothing goes out to the API
EDIT:
This is the route that my Ember app is using for /machines/:machine_id/service-orders:
export default Ember.Route.extend(MachineFunctionalRouteMixin, {
model: function() {
var machine = this.modelFor('machines.show');
var serviceOrders = machine.get('serviceOrders');
return serviceOrders;
},
setupController: function(controller, model) {
this._super(controller, model);
}
});
And the model for machines/show:
export default Ember.Route.extend({
model: function(params) {
var machine = this.store.find('machine', params.machine_id);
return machine;
},
setupController: function(controller, model) {
this._super(controller, model);
var machinesController = this.controllerFor('machines');
machinesController.set('attrs.currentMachine', model);
}
});
Intuitively, I would think that machine.get('serviceOrders'); would make a call to the API that would be intercepted and handled by Mirage. Which does not seem to be the case