Aborting asynchronous apex (future call) from trigger? Queuable Interface solution? - triggers

I'm currently working on something that involves iterating through a Sales Order and Sales Order Products via a trigger on the Sales Order object. I've created an Apex class that is called from the Sales Order after update trigger. The trigger passes a string (Sales Order Id) to the static method of the class. This future call method queries for Sales Order Products that belong to the Sales Order id, and makes a web service call for each item in the collection. This all works great, however I would like for this process to be more robust and handle errors more intelligently. What I would like to be able to do is abort the whole process when the method encounters something it doesn't like, let's say it identifies a product in the order it doesn't like as an example. The only process I've found that can handle aborting is via the Queueable Interface, and calling the class via System.enqueueJob(). This however doesn't help me as I cannot for the life of me figure out a way to pass any parameters to this class when System.enqueueJob() is invoked, since the class methods are static and the interface forces the process to run from the execute() method, which only takes a Context parameter. Am I going down the wrong road with this? The only other possibility I was thinking of was to just create methods for all of the subprocesses in my class and return from those if they encounter any errors and set a bool flag that can be used to skip processes afterward in the class. Sorry if this doesn't make sense, if so let me know and I'll try to provide more information.

You can pass parameters to a Queueable job in the constructor. i.e.:
System.enqueueJob(new myQueueableClass(salesOrderId));
You need to add a constructor in your Queueable class that will accept the Sales Order Id and store it in a private variable also declared inside the Queueable class, which then can be accessed by the execute() method.

Related

CQRS - How to handle if a command requires data from db (query)

I am trying to wrap my head around the best way to approach this problem.
I am importing a file that contains bunch of users so I created a handler called
ImportUsersCommandHandler and my command is ImportUsersCommand that has List<User> as one of the parameters.
In the handler, for each user that I need to import I have to make sure that the UserType is valid, this is where the confusion comes in. I need to do a query against the database, to get list of all possible user types and than for each user I am importing, I want to verify that the user type id in the import matches one that is in the db.
I have 3 options.
Create a query GetUserTypesQuery and get the rest of this and then pass it on to the ImportUsersCommand as a list and verify inside the command handler
Call the GetUserTypesQuery from the command itself and not pass it (command calling another query)
Do not create a GetUsersTypeQuery and just do the query results within the command (still a query but no query/handler involved)
I feel like all these are dirty solutions and not the correct way to apply CQRS.
I agree option 1 sounds the best but would maybe suggest adding a pre handler to validate your input?
So ImportUsersCommandHandler deals with importing you data (and only that) and add a handler that runs before that validates (in your example, checks the user types and maybe other stuff) and bails out of it does not pass. So it queries the db, checks the usertypes and does whatever it needs to if it fails. Otherwise it just passes down to your business handler (ImportUsersCommandHandler).
I am used to using Mediatr in NET Core and this pattern works well (this is what we do) so sorry if this does not fit with your environment/setup!

Get int value from database

How i can get int value from database?
Table has 4 columns
Id, Author, Like, Dislike.
I want to get Dislike amount and add 1.
i try
var db = new memyContext();
var amountLike = db.Memy.Where(s => s.IdMema == id).select(like);
memy.like=amountLike+1;
I know that this is bad way.
Please help
I'm not entirely sure what your question is here, but there's a few things that might help.
First, if you're retrieving via something that reasonably only has one match, or in a scenario where you want just one thing, then you should be use SingleOrDefault or FirstOrDefault, respectively - not Where. Where is reserved for scenarios where you expect multiple things to match, i.e. the result will be a list of objects, not an object. Since you're querying by an id, then it's fairly obvious that you expect just one match. Therefore:
var memy = db.Memy.SingleOrDefault(s => s.IdMema == id);
Second, if you just need to read the value of Like, then you can use Select, but here there's two problems with that. First, Select can only be used on enumerables, as already discussed here, you need a single object, not a list of objects. In truth, you can sidestep this in a somewhat convoluted way:
var amountLike = db.Memy.Select(x => x.Like).SingleOrDefault(x => x.IdMema == id);
However, this is still flawed, because you not only need to read this value, but also write back to it, which then needs the context of the object it belongs to. As such, your code should actually look like:
var memy = db.Memy.SingleOrDefault(s => s.IdMema == id);
memy.Like++;
In other words, you pull out the instance you want to modify, and then modify the value in place on that instance. I also took the liberty of using the increment operator here, since it makes far more sense that way.
That then only solves part of your problem, as you need to persist this value back to the database as well, of course. That also brings up the side issue of how you're getting your context. Since this is an EF context, it implements IDisposable and should therefore be disposed when you're done with it. That can be achieved simply by calling db.Dispose(), but it's far better to use using instead:
using (var db = new memyContext())
{
// do stuff with db
}
And while we're here, based on the tags of your question, you're using ASP.NET Core, which means that even this is sub-optimal. ASP.NET Core uses DI (dependency injection) heavily, and encourages you to do likewise. An EF context is generally registered as a scoped service, and should therefore be injected where it's needed. I don't have the context of where this code exists, but for illustration purposes, we'll assume it's in a controller:
public class MemyController : Controller
{
private readonly memyContext _db;
public MemyController(memyContext db)
{
_db = db;
}
...
}
With that, ASP.NET Core will automatically pass in an instance of your context to the constructor, and you do not need to worry about creating the context or disposing of it. It's all handled for you.
Finally, you need to do the actual persistence, but that's where things start to get trickier, as you now most likely need to deal with the concept of concurrency. This code could be being run simultaneously on multiple different threads, each one querying the database at its current state, incrementing this value, and then attempting to save it back. If you do nothing, one thread will inevitably overwrite the changes of the other. For example, let's say we receive three simultaneous "likes" on this object. They all query the object from the database, and let's say that the current like count is 0. They then each increment that value, making it 1, and then they each save the result back to the database. The end result is the value will be 1, but that's not correct: there were three likes just added.
As such, you'll need to implement a semaphore to essentially gate this logic, allowing only one like operation through at a time for this particular object. That's a bit beyond the scope here, but there's plenty of stuff online about how to achieve that.

Querying Azure Mobile App TableController

I'm using Azure Mobile Apps and TableControllers in my project. Development has been going quite smoothly, until now. One of my tables relies on quite a bit of business logic in order to return the appropriate entities back to the client. To perform this business logic I need to get some parameters from the client (specifically, a date range).
I know I could use an APIController to return the data, but won't that break the entity syncing that's provided by the SyncTables in Xamarin?
My current logic in my GetAll is:
public IQueryable<WorkItemDTO> GetAllWorkItem()
{
//Return all the work items that the user owns or has been assigned as a resource.
var query = MappedDomainManager.QueryEntity().Where(x => x.OwnerId == UserProfileId || x.Resources.Where(r => r.AssignedResourceId == UserProfileId).Count() > 0);
return query.Project().To<WorkItemDTO>();
}
What I would like is to be able to somehow pass through a start and end date that I can then use to build up my list of WorkItemDTO objects. The main problem is that a WorkItem entity can actually spawn off multiple WorkItemDTO objects as a WorkItem can be set to be recurring. So for example say a WorkItem is recurring once a week, and the user wants to see a calendar for 1 month, that single WorkItem will spawn 4 separate concrete WorkItemDTO objects.
Then when a user modifies one of those WorkItemDTO objects on the client side, I want it to be sent back as a patch that creates its own WorkItem entity.
Does anyone know how I can get a TableController to receive parameters? Or how to get an APIController to work so that client syncing isn't affected?
Any help would be appreciated.
Thanks
Jacob
On the server, you can add a query parameter to the table controller get method easily, by adding a parameter with the right name and type.
For instance, you could add a dateFilter query parameter as follows:
public IQueryable<WorkItemDTO> GetAllWorkItem(string dateFilter)
This would be called by passing a dateFilter=value query parameter. You can use any data type that ASP.NET Web API supports in serialization. (Note that if you don't have a GetAll that takes no query parameters, you will get an Http 405 Method Not allowed if you do a Get without this query parameter.)
On the client, as noted by #JacobJoz, you just use the method IMobileServiceTableQuery.WithParameters to construct the query that is passed to PullAsync. If you have multiple incremental sync queries against the same table and they use different values for the parameters, you should make sure to include those in the queryId to pull.
That is, if you have one query with parameters foo=bar and another that is foo=baz for the same sync table, make sure you use two different query IDs, one that includes "bar" and one that includes "baz". Otherwise, the 2 incremental syncs can interfere with one another, as the queryId is used as a key to save the last updated timestamp for that sync table. See How offline synchronization works.
The part that is unfortunately hard is passing the query parameter as part of the offline sync pull. Offline sync only works with table controllers, FYI.
There is an overloaded extension method for PullAsync that takes a dictionary of parameters, but unfortunately it requires a string query rather than IMobileServiceTableQuery:
PullAsync(this IMobileServiceSyncTable table, string queryId, string query, IDictionary<string, string> parameters, CancellationToken cancellationToken)
(I've filed a bug to fix this: Add a generic PullAsync overload that accepts query parameters).
The problem is that there's no easy way to convert from IMobileServiceTableQuery to an OData query string, since you'd need to access internal SDK methods. (I filed another issue: Add extension method ToODataString for IMobileServiceTableQuery.)
I've looked through the source code for MobileServiceTableQuery on github. It looks like it exposes a method called WithParameters. I have chained that method call onto CreateQuery in order to generate the query to the server, and it seems to do what I want.
Here is the client code:
var parameters = new Dictionary<string, string>();
parameters.Add("v1", "hello");
var query = WorkItemTable.CreateQuery().WithParameters(parameters);
await WorkItemTable.PullAsync("RetrieveWorkItems", query);
On the server I have a GetAll implementation that looks like this:
public IQueryable<WorkItem> GetAllWorkItem(string v1)
{
//return IQueryable after processing business logic based on parameter
}
The parameterized version of the method gets called successfully. I'm just not entirely sure what the impacts are from an incremental pull perspective.

CQRS and REST HATEOAS mismatch

Suppose you have a model Foo.
One business case is to simply create an instance of Foo, so there is a corresponding CreateFooCommand in my model, triggered by invoking a POST request to a given REST endpoint.
There are of course other Commands too.
But now, there is a ViewModel, which is derived from my DomainModel. It's simply a sql table with raw data - each Foo instance from DomainModel has corresponding derived ViewModel instance. Both have different IDs (on DomainModel there is a DomainID, on ViewModel it's simply a long value).
Now: should I even care about HATEOAS in such a case? In a proper REST implementation, I should at least return location-url in the header. But since my view model is only derived from DomainModel, should I care? I don't even have the view model's ID at the time my DomainModel is created.
Since CQRS means that Queries are separated from Commands, you may not be able to perform a Query right away, because the Command may not yet have been applied (perhaps it never will).
In order to reconcile that with HATEOAS, instead of returning 200 OK from the POST request, the service can return 202 Accepted:
The request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place. There is no facility for re-sending a status code from an asynchronous operation such as this.
The 202 response is intentionally non-committal. Its purpose is to allow a server to accept a request for some other process (perhaps a batch-oriented process that is only run once per day) without requiring that the user agent's connection to the server persist until the process is completed. The entity returned with this response SHOULD include an indication of the request's current status and either a pointer to a status monitor or some estimate of when the user can expect the request to be fulfilled.
(My emphasis)
That pointer could be a link that the client can query to get the status of the Command. When/if the Command completes and the View is updated, that status resource could then contain a link to the view.
This is pretty much a workflow straight out of REST in Practice - very reminiscent of its Restbucks example.
Another option to deal with the ID issue is to generate the ID before accepting the Command - perhaps even asking the client to supply the ID. Read more about such options here.
As Greg Young explains, CQRS is nothing more than "splitting one object into two". So assume that you have one domain aggregate and it has an id. Now you are talking about your view model having another id. However, you are unable to update your view model unless you have the aggregate id in your view model as well. From my point of view, your REST POST request should return a result that has the aggregate id in it. This is your id, the view model id has no interest to anyone except the read model storage.
Should it return a command status URI like Mark suggests is a topic for another discussion. Many CQRS practitioners currently tend to handle commands synchronously to avoid FE/BE mismatch in case of failure and give the FE an ability to react on errors on the BE. There is no real win to execute commands asynchronously for one user. Commands do mutate the state and in 99% of cases the user needs to know if the state was mutated properly.

Matlab: OOPS : Event Block: Dynamically (Programmatically) adding events at run-time

I am trying to write a matlab class which accepts request for financial data and later asynchronously provides the data by triggering events. The whole logic can be defined as following.
1) Get request for data on Security (SecId) with a callback func handle (#func)
2) Add a listener with event name "evnt_SecId" and callback func #func.
3) Collect all data, filter them by securities and fire event specific to a particular security.
Now everything seems to be easy and doable in Matlab except that I cannot dynamically define events. Currently, I must define events for each SecId in the { events ... end } block.
Does anyone knows of a way to dynamically declare events as the request arrive?
Alternate Solution that I thought of : I can have one update "event" and all listener associated with it while the filtering for SecId takes place in the callbacks. This solution is unacceptable due to performance reasons.
How about this:
make SecId a subclass of dynamicprops
instead of adding a regular listener, add a PostSet propListener and dynamically add a
new property
send the message by setting the value of the property.
I have no idea about the performance characteristics of that solution, but it might do what you need.
How about filtering for the SecId in the "master" event firing method? This way the filtering only happens once per fired event. The class must than associated the listeners it has with the SecId it was registered for.