There are many ways to do this, but I prefer to keep a message-based system as decoupled as possible. This means the overall system cannot read the state of any component, nor any component read the state of any other (as that way lies spaghetti ties of dependancies).
So, while the running system will look after itself, we need a way to tell each component to start itself up, and we already have such a thing in the component registration, ie at startup the core system has to inform each component that it is now registered (or will ask each component to return its details so it can be registered). This is the stage at which the component can perform its startup tasks, and can send messages as it would do in normal operation.
So the brake pedal, when the ignition is started, would receive a registration/check message from the car management and it would return not only a "I'm here and working" message, but it would then check its own state and send the messages for that state (eg a pedal depressed message).
The problem then becomes one of startup dependancies, as if the brake light is not yet registered then it will not receive the message, but this is easily resolved by queuing all of these messages until the core system has completed its startup, registration and check routine.
The biggest benefit is that there is no special code required to handle initialisation except that you already have to write (ok, if your message-sending for brake pedal events is in a brake-pedal handler you will have to call that in your initialisation too, but that's usually not a problem unless you've written that code tied heavily to the handler logic) and no interaction between components except those that they already send to each other as normal. Message passing architectures are very good because of this!
Synchronous calls are only a problem when the work required is slow.
Since you just have to check a db, You can have a queue for cancellation validation requests with an RPC style return queue and call it from your REST service, while keeping the incoming request waiting.
Where you might end up with issues is when the Order Placement message is still on the queue to be processed and you get a cancel for it. It doesn't seem unsolvable though.
If the cancel request processing was slow, well then yes, you would have no choice but to adapt your workflow to an async one.
My general advice would be: If you are using message queues, make your microservices a bit bigger than you would otherwise. Just to keep the number of internal message types down to a manageable level.
I probably would have the rest service check the db directly. If you need a message to trigger other stuff you can always fire off a CancellationRequestProccessed or something at the same time as doing the actual work.
Best Answer
Reactive Programming
A number of people have identified an increasing importance of a certain combination of desired properties for a certain kind of modern large-scale software systems. In concert, these properties satisfy typical non-functional requirements related to scalability, flexibility, robustness, ressource consumptions etc. This emerging notion has been coined reactiveness and the set of properties that constitute reactive systems has been defined in the reactive manifesto. The main characteristics are: responsiveness, resiliency, elasticity, and being message-driven. Currently, this is probably the most widely agreed-upon definition of reactive systems. Based on this general notion of reactive systems, reactive programming can be assumed to refer to any paradigm, pattern or technique that facilitates the realization of these properties in software.
Having said that, on a more technical level, reactive programming currently is understood as a programming model that has traditionally been known as dataflow programming that is having a renaissance because it is leveraged in an increasing amount of programming languages, frameworks and libraries to provide the aforementioned properties.
The systems from which the properties that constitute reactive systems have been derived typically make use of a variant of dataflow programming in which explicit handling of messages between components facilitates fault-tolerancy, the handling of back pressure and enable efficient use of ressources in highly dynamic settings by non-blocking communication.
Event-Driven Architecture
Event-driven architecture is a rather vaguely defined umbrella term for architecural patterns that certain people have identified as of increasing usefulness for certain applications. In this case, the notion largely stems from patterns that have emerged in the community of enterprise software in which microservices have emerged as a decomposition and deployment pattern to provide certain organizational benefits, i.e. to help distribute work within large projects.
While many classic concepts in software development such as object-oriented programming can be considered event-driven - communication between actors can be considered as events - it is especially this incarnation of designing an application by considering events as basic building blocks that is currently understood as event-driven. Often times people also associate with the term several patterns that extend this basic idea such as event-sourcing, and CQRS to provide several benefits that currently appear benefitial for certain applications.
Comparison
In comparison, at the heart of both notions lies asynchronous communication to decouple components. Events and messages are related notions, mostly differing in the intent that is emphasized by each term. As such they are a common ingredient of both notions. In a strict sense, being event-driven, today, is a prerequisite for being responsive. Personally, I can imagine that other paradigms may emerge to achieve the desired behavioral properties of reaponsive systems.
While the reactive manifesto emphasizes the above mentioned quality attributes related to how the system behaves at runtime and responds dynamically, event-driven architecture focuses on how a system is decomposed and how its parts generally interact. In this sense, the perspective of reactive systems is a rather behavioristical one, even though it assumes certain properties related to its internal behavior, my impression is that these internal properties may be accidental in nature, i.e. the desired behavioral properties could be achieved by different means.
Each notion currently takes a different perspective on a software system, comes with a different set of typical associations, emphasizes different aspects and focuses on achieving different goals. However they will likely keep being recoined and might diverge or converge as the notions evolve.