I've got some data that it being written into a table by another application.
I could write some polling code? But I wondered if there was some way of getting EntityFramwork to handle this.
Something like ...
database.MyDbSet.Select(x => x.Id = "my id").WhenAvailableAsync() ?
Am I just dreaming? :)
You can always make a call via Task.Run. For example:
public async Task<MyModel> GetSomethingAsync(int id)
{
return await Task.Run(() => database.MyDbSet.Select(x => x.Id == id));
}
That should be able to give you what you want.
Related
I want to display data from OMDB API on Dialogflow GUI but it's not happening. Data is being displayed fine on Google Cloud Console.
function infoHandler(agent){
let movieName = agent.parameters.movie;
agent.add(`The information for ${movieName} is as follow`);
fetch('http://www.omdbapi.com/?apikey=e255decd%20&s='+ movieName)
.then(result => result.json())
.then((json) => {
let id = json.Search[0].imdbID;
fetch('http://www.omdbapi.com/?apikey=e255decd%20&i=' + id)
.then(result => result.json())
.then((json) => {
agent.add(json.Title + json.Plot + json.imdbRatinng);
return;
}).catch((ex) => {
console.log(ex);
});
})
.catch((e) => {console.log(e);});
The issue is that fetch() causes an asynchronous operation. However, there is nothing that indicates to the Dialogflow handler dispatcher that it is asynchronous and that it should wait for it to complete before sending back a reply. To do that, you'd need to return a Promise.
Fortunately the then/catch chain that you have that are built off the fetch() return a Promise. So all you need to do is return the Promise that they have. This is as simple, in your case, by placing a return before the fetch() call. So it would look something like this:
return fetch('http://www.omdbapi.com/?apikey=e255decd%20&s='+ movieName)
// Other lines remain the same
Inspired by Akavache I am trying to create a solution that provides me with an IObservable<IArticle>. The method essentially first try to get all the articles that are present in the database, then it tries to fetch updated articles from the webservice and as it is getting the latest articles from webservice it tries to save them back to the database.
Since the webservice is essentially a cold observable and I don't want to subscribe twice, I used Publish to connect to it. My understanding is that I am using the correct version of the Publish method, however, many times the method tend to miss first couple of Articles from the GetNewsArticles. This was observed through the UI and also the Trace calls added in the call below.
Apart from solving the problem, it would be great to also understand how to debug/test this code (apart from introducing DI to inject NewsService).
public IObservable<IArticle> GetContents(string newsUrl, IScheduler scheduler)
{
var newsService = new NewsService(new HttpClient());
scheduler = scheduler ?? TaskPoolScheduler.Default;
var fetchObject = newsService
.GetNewsArticles(newsUrl,scheduler)
.Do(x => Trace.WriteLine($"Parsing Articles {x.Title}"));
return fetchObject.Publish(fetchSubject =>
{
var updateObs = fetchSubject
.Do( x =>
{
// Save to database, all sync calls
})
.Where(x => false)
.Catch(Observable.Empty<Article>());
var dbArticleObs = Observable.Create<IArticle>(o =>
{
return scheduler.ScheduleAsync(async (ctrl, ct) =>
{
using (var session = dataBase.GetSession())
{
var articles = await session.GetArticlesAsync(newsUrl, ct);
foreach (var article in articles)
{
o.OnNext(article);
}
}
o.OnCompleted();
});
});
return
dbArticleObs // First get all the articles from dataBase cache
.Concat(fetchSubject // Get the latest articles from web service
.Catch(Observable.Empty<Article>())
.Merge(updateObs)) // Update the database with latest articles
.Do(x => Trace.WriteLine($"Displaying {x.Title}"));
});
}
UPDATE - Added GetArticles
public IObservable<IContent> GetArticles(string feedUrl, IScheduler scheduler)
{
return Observable.Create<IContent>(o =>
{
scheduler = scheduler ?? DefaultScheduler.Instance;
scheduler.ScheduleAsync(async (ctrl, ct) =>
{
try
{
using (var inputStream = await Client.GetStreamAsync(feedUrl))
{
var settings = new XmlReaderSettings
{
IgnoreComments = true,
IgnoreProcessingInstructions = true,
IgnoreWhitespace = true,
Async = true
};
//var parsingState = ParsingState.Channel;
Article article = null;
Feed feed = null;
using (var reader = XmlReader.Create(inputStream, settings))
{
while (await reader.ReadAsync())
{
ct.ThrowIfCancellationRequested();
if (reader.IsStartElement())
{
switch (reader.LocalName)
{
...
// parsing logic goes here
...
}
}
else if (reader.LocalName == "item" &&
reader.NodeType == XmlNodeType.EndElement)
{
o.OnNext(article);
}
}
}
o.OnCompleted();
}
}
catch (Exception e)
{
o.OnError(e);
}
});
return Disposable.Empty;
});
}
UPDATE 2
Sharing the link to source code here.
There's a few things I don't like about your code. I assume NewsService is an IDisposable as it takes an HttpClient (which is disposable). You're not doing a proper clean up.
Also, you haven't provided a complete method - because you've tried cutting it down for the question - but that makes it hard to reason about how to rewrite the code.
That said, the one thing that sticks out to me as quite horrid looking is the Observable.Create. Can you please try this code instead and see if it helps things work for you?
var dbArticleObs =
Observable
.Using(
() => dataBase.GetSession(),
session =>
from articles in Observable.FromAsync(ct => session.GetArticlesAsync(newsUrl, ct))
from article in articles
select article);
Now, if that does, try rewriting fetchObject to use the same Observable.Using when newing up the `NewService.
In any case, it would be good if you could provide a complete implementation of GetContents, NewsService and your dataBase code in your question.
I have this method on bloc
fetchProductAttribute(int _prodId) async {
List<ProductAttribute> productAttribute = await _repository.fetchProductAttribute(_prodId).catchError((err) => _fetcher.addError(err));
_fetcher.sink.add(productAttribute);
}
This will call repository then rest api to the backend. Now I want to filter this data.
I will modify this but it's not working... How to do this properly?
fetchProductAttribute(int _prodId) async {
List<ProductAttribute> productAttribute = await _repository.fetchProductAttribute(_prodId).catchError((err) => _fetcher.addError(err));
for(var c in productAttribute){
if(c.variant==true){
_fetcher.sink.add(productAttribute);
}
}
}
All data still coming up...I want only data with variant true to be displayed on screen. How to do this?
I seen one article on how to do filtering on Stream by using StreamSubscription here and here but this is not what I want. I want to filter out from the earlier part of REST.
As one comment said, use the where operator over the list.
fetchProductAttribute(int _prodId) async {
List<ProductAttribute> productAttribute = await _repository.fetchProductAttribute(_prodId).catchError((err) => _fetcher.addError(err));
productAttribute = productAttribute.where((c) => c.variant == true).toList()
_fetcher.sink.add(productAttribute);
}
I'm new to Sails.js and I'm looking to develop a new application using sail.js and in this application, I want to respond to a POST request as quickly as possible, then handle a number of tasks with the payload asynchronously. Ideally I'd have a helper for each step of the tasks I want to carry out on the payload and chain them all asynchronously in the action. I've been trawling through the docs and can't seem to find a way to do this.
Is this the right way to approach this issue (if so how/can you point me to docs) or are there alternative ways to handle this issue that I have overlooked?
Thanks
With ES6, you can use helpers both with async/await or as promises.
const temp1 = await sails.helpers.stepone();
const temp2 = await sails.helpers.steptwo( temp1 );
let result = await sails.helpers.stepthree( temp2 );
// use result here
OR
sails.helpers.stepone
.then(sails.helpers.steptwo)
.then(sails.helpers.stepthree)
.then(result => {
// use result here
});
Just set up your service methods as promises and resolve early. You can import bluebird, for example, to accomplish this.
In your controller:
myPostEndpoint: (req, res) => {
return MyProcessorService.initProcessing(req.body).then(res.json);
}
And in your service MyProcessorService:
var Promise = import('bluebird');
//... other init code
module.exports = {
initProcessing: data => {
//do some validation...
// then just resolve and continue
Promise.resolve({ status: 'processing'});
return MyProcessorService.step1(data)
.then(MyProcessorService.step2)
.then(MyProcessorService.step3)//and so on....
},
step1: dataFromInit => {
//do stuff and resolve for step2
},
step2: dataFromStep1 => {
//do stuff and resolve for step3
},
step3: dataFromStep2 => {
//do stuff and resolve
},
//and so on
}
You could also set up a worker queue with something like Bull and Redis to send off jobs to and run in a WorkerService or separate worker app.
I have an ASP.NET Core website, using EFCore.
I would like to do some work like logging to the database, but after having sent the response to the user in order to answer faster.
I could do it in a different thread, but due to async access of the DbContext I am not sure it is safe. Is there any recommended way to do that?
public async Task<IActionResult> Request([FromForm]RequestViewModel model, string returnUrl = null)
{
try
{
var newModel = new ResponseViewModel(model);
// Some work
return View("RequestView",newModel)
}
finally
{
// Some analysis on the request
// I would like to defer this part
await Log(model);
}
}
One of the reason is that I would like to call a web-service (geocoding), which is not needed to answer, but good to work on the log (I need the city/country of coordinates).
I see this has never been answered, but actually have a solution.
The simple solution:
public async Task<IActionResult> Request([FromForm]RequestViewModel model, string returnUrl = null)
{
try
{
var newModel = new ResponseViewModel(model);
// Some work
return View("RequestView",newModel)
}
finally
{
Response.OnCompleted(async () =>
{
// Do some work here
await Log(model);
});
}
}
The secure solution, as OnCompleted used to be called before the response being sent, so delaying the response:
public static void OnCompleted2(this HttpResponse resp, Func<Task> callback)
{
resp.OnCompleted(() =>
{
Task.Run(() => { try { callback.Invoke(); } catch {} });
return Task.CompletedTask;
});
}
and call Response.OnCompleted2(async () => { /* some async work */ })
Building on Jeans answer and a question and answer on the try - return - finally pattern, the try and finally blocks can be removed (if you don't really want to catch an exception).
This leads to the following code:
public async Task<IActionResult> Request([FromForm] RequestViewModel model, string returnUrl = null)
{
var newModel = new ResponseViewModel(model);
// Some work
Response.OnCompleted(async () =>
{
// Do some work here
await Log(model);
});
return View("RequestView", newModel);
}
There's no out of the box way to do what you want.
But, here's a possible approach:
Have a queue and a worker (thread or process)
Just before the request is sent back to the client, add a message in that queue
The worker will pick up that message at some point in the future, and process it.
Since the worked runs somewhere else and not on the request thread, the server can complete the request thread and the worker can do what's left.
Try using Hangfire. Hangfire is an easy way to perform background processing in .NET and .NET Core applications. No Windows Service or separate process required.
Backed by persistent storage. Open and free for commercial use.
You could do something like
var jobId = BackgroundJob.Enqueue(() => Log(model));
And here is my blog post on using HangFire in ASP.NET Core
Create a new class that inherits from ActionFilterAttribute, overwrite the OnResultExecuted method to perform the logging and then apply your attribute class to the controller actions you want to do logging.