How to handle command type operations? - spartacus-storefront

I am fairly new with Commands and Queries in Spartacus. Let me ask with an example. Let's say I am calling this method
checkoutDeliveryAddressFacade.createAndSetAddress(address) which is returning an Observable<Unknown>. When the Observable emits, can I assume the operation completed on the backend? How do I know if the operation has succeeded or not? Do I need to call getDeliveryAddressState after calling createAndSetAddress?

Related

How to tell if middleware contains a Run()?

Is there any way to tell in ASP.NET Core if any given middleware will contain a Run() call which will stop the pipeline? It seems that UseMvc() is one big one, but I am not even certain about that, I just keep reading that it needs to go at the end, I assume it is because it contains a call to Run().
Perhaps there is a way to generate a visualisation of the pipeline for all middleware currently in use, showing which one contains the Run() call?
There is no sure way to tell, beyond reading documentation on each specific piece of middleware.
quoting itminus in the comments on my question:
Not only Run(), but also MapWhen() will terminate the process. Also, anyone could create a custom middleware that doesn't invoke the next delegate and then cause to a terminate.
It's the duty of middleware to determine whether there's a need to to call next. There's no built-in way to visualize the pipeline except you read the document/source code. That's because all the middlewares will be built into a single final delegate at startup time. When there's an incoming message, the final delegate will be used to process requests. As a programmer, we know what will be done by the middlewares, we know the time when it branches, and we know the time it terminates that's because we write the code. But the program won't know it until it actually runs just because the final delegate is built at startup time.

Command Pattern clarification

I cannot see any of the command pattern classes e.g. invoker, receiver manifesting in the accepted answer of the following link Long list of if statements in Java. I have gone with the accepted answer to solve my 30+ if/else statements.
I have one repository that I am trying to pass DTOs to save to the database. I want the repository to invoke the correct save method for the DTO so I am checking the instance type at runtime.
Here is the implementation in Repository
private Map<Class<?>, Command> commandMap;
public void setCommandMap(Map<Class<?>, Command> commandMap) {
this.commandMap = commandMap;
}
and a method that will populate the commandMap
commandMap.put(Address.class, new CommandAddress());
commandMap.put(Animal.class, new CommandAnimal());
commandMap.put(Client.class, new CommandClient());
and finally the method that saves
public void getValue(){
commandMap.get(these.get(0).getClass()).save();
}
The service class that uses the Repo registers the commandMap.
Does the accepted answer represent a sort of (approximate) implementation of the Command pattern?
It seems like an enum that implements an exec interface will eliminate your if/else problem or turn it into a switch.
It does not look like you need a command patterm.
Gof says:
Use the Command pattern when you want to
parameterize objects by an action to perform, as MenuItem objects did above. You can express such parameterization in a procedural language with a callback function, that is, a function that's registered somewhere to be called at a later point. Commands are an object-oriented replacement for callbacks.
specify, queue, and execute requests at different times. A Command object can have a lifetime independent of the original request. If the receiver of a request can be represented in an address space-independent way, then you can transfer a command object for the request to a different process and fulfill the request there.
support undo. The Command's Execute operation can store state for reversing its effects in the command itself. The Command interface must have an added Unexecute operation that reverses the effects of a previous call to Execute. Executed commands are stored in a history list. Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling Unexecute and Execute, respectively.
support logging changes so that they can be reapplied in case of a system crash. By augmenting the Command interface with load and store operations, you can keep a persistent log of changes. Recovering from a crash involves reloading logged commands from disk and reexecuting them with the Execute operation.
structure a system around high-level operations built on primitives operations. Such a structure is common in information systems that support transactions. A transaction encapsulates a set of changes to data. The Command pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions.
Which of the above do you want to do?

How to test handle_cast in a GenServer properly?

I have a GenServer, which is responsible for contacting an external resource. The result of calling external resource is not important, ever failures from time to time is acceptable, so using handle_cast seems appropriate for other parts of code. I do have an interface-like module for that external resource, and I'm using one GenServer to access the resource. So far so good.
But when I tried to write test for this gen_server, I couldn't figure out how to test the handle_cast. I have interface functions for GenServer, and I tried to test those ones, but they always return :ok, except when GenServer is not running. I could not test that.
I changed the code a bit. I abstracted the code in handle_cast into another function, and created a similar handle_call callback. Then I could test handle_call easily, but that was kind of a hack.
I would like to know how people generally test async code, like that. Was my approach correct, or acceptable? If not, what to do then?
The trick is to remember that a GenServer process handles messages one by one sequentially. This means we can make sure the process received and handled a message, by making sure it handled a message we sent later. This in turn means we can change any async operation into a synchronous one, by following it with a synchronisation message, for example some call.
The test scenario would look like this:
Issue asynchronous request.
Issue synchronous request and wait for the result.
Assert on the effects of the asynchronous request.
If the server doesn't have any suitable function for synchronisation, you can consider using :sys.get_state/2 - a call meant for debugging purposes, that is properly handled by all special processes (including GenServer) and is, what's probably the most important thing, synchronous. I'd consider it perfectly valid to use it for testing.
You can read more about other useful functions from the :sys module in GenServer documentation on debugging.
A cast request is of the form:
Module:handle_cast(Request, State) -> Result
Types:
Request = term()
State = term()
Result = {noreply,NewState} |
{noreply,NewState,Timeout} |
{noreply,NewState,hibernate} |
{stop,Reason,NewState}
NewState = term()
Timeout = int()>=0 | infinity
Reason = term()
so it is quite easy to perform unit test just calling it directly (no need to even start a server), providing a Request and a State, and asserting the returned Result. Of course it may also have some side effects (like writing in an ets table, modifying the process dictionary...) so you will need to initialize those resources before, and check the effect after the assert.
For example:
test_add() ->
{noreply,15} = my_counter:handle_cast({add,5},10).

Sencha Touch store sync callback

My store.sync() can return success:false, and if it does, I would like to use something similar to Ext's failure callback to react to the error appropriately, but I did not find a possibility to use any builtin ST functions for this. sync has neither callback nor success nor failure option available in ST.
What did I overlook?
PS: I did find a workaround for success callback at Why is there no sync callback in Sencha Touch? but I need failure callback.
store.sync() is not where you need to look. Take a look at the proxy. Most likely you are using an Ajax request and that in turn will deliver a detailed success and failure.
I am now calling Ext.data.Model.save() on all Ext.data.Model instances that are dirty. This won't batch everything neatly together, but in 90% of the cases, only one item is edited anyways. The best is that this allows to check for failure on each and every item, and not only on the whole batch.

Predis Aysnc Doubts

I was told that if I want to use predis-async, then I will use some kind of async web framework (probably built using https://github.com/reactphp/react). I am currently using Yii.
I was also told that
$client->getEventLoop()->run();
That line will start event loop which won't return after all connections to Redis are terminated and all callbacks are invoked. So that means that this line will be blocking for your code. Try to run following code (the simplest code illustrating Predis Async usage):
$client = new Predis\Async\Client('tcp://127.0.0.1:6379');
$client->set('test', 'value');
$client->getEventLoop()->run();
echo 'END';
END won't be probably displayed for a long time or maybe never, but for sure it will take more than the same operation using non-Async
Predis.
However, my own understanding is that existing PHP system should be able to use Predis Async right out of the box, as a lib. Which means existing PHP system does not need to be on ReactPHP. My idea of using predis async is similar to using mongodb asynchronous
commit. When PHP calls mongodb lib to commit a write operation, it is
asynchronous. Mongodb immediately returns the call rather than waiting for
the write happens first. In this case, mongodb doesn't requires
asynchronous php framework too.
Is it true that
END won't be probably displayed for a long time or maybe never, but
for sure it will take more than the same operation using non-Async
Predis.