- Removed constructor in InMemoryFunctionCatalog that creates empty maps and no registrations since there is no way to register anything after catalog is created.
- Refactored registration logic a bit more functional/concise in the FunctionRegistration constructor of InMemoryFunctionCatalog
- Added additional assertions in tests
rebased and removed the assertion that was causing certain test failures
If the incoming message has a stream_routekey header, we use that
to route the message to a named function. Also adding the header
to messages coming out of suppliers.
The biggest change here is sort of orthogonal: it fixes a bug where
Spring Integration would subscribe twice to the same input channel
if the FunctionCatalog contains both functions and consumers. Then
when a message comes in it is dispatched to one or the other, but not
both. So the routing key couldn't work without fixing that
problem.
Also applies to output types, wrapper types and identifying if
messages can be processed directly.
See gh-81 (the ambiguity is still there, but the indirection bug
is fixed).
Functions are namespaced under the "app name", e.g.
/sample/uppercase is the "uppercase" function in the "sample" app.
Also added a README to get started quickly.
The controller doesn't need to know the mappings, and it helps
to keep them closer to the actual AppDeployer, so in a future
change we can use the app names to look up functions.
* If there is only one function, use it unconditionally
* If no functions match, ensure that null is not the selector
* If a conversion succeeds, check the type of the result
Spring Boot apps often run with --debug (no boolean value), so
we need to be defensive and not barf if it's empty (and therefore
not convertible to a boolean)
The io.spring sample referred to in the openwhisk README isn't
in this repo, so users generally don't have it installed locally.
This change makes it more obvious that you have to create your
own.
Also fixes the `wsk ...` command lines (the order of arguments
was wrong - maybe the CLI changed?).
If the output is a Message we grab the headers from the first one
and send those as response headers.
A function can add headers to messages. The HTTP response will
contain only headers that are in x-* _or_ were added to the message
by user (i.e. they weren't in the request).
We certainly do not want to pass through all HTTP headers (request
headers can conflict with or invalidate response headers).
The FunctionInspector needs to be able to distinguish between a
function of Flux<Foo> and a function of Flux<Message<Foo>>. Then
it can do the conversion a level below.
Only supports Message->Message or POJO->POJO (no mixtures), so there
is only one new method in FunctionInspector.
No support in the web endpoints yet. But it's probably not so hard
to add.
If there is only one function you shouldn't have to set any configuration
to get a stream app to run. This also implementation supports multiple
functions, trying to guess which one to use based on the type of
the incoming message payload. In principle that could be strategized
as a simple router function (e.g. to look for a header with a function
name).
If there are functions and consumers in the same app, they will
subscribe to the same input channel (and hence by default Spring
Integration will load balance between them). This could also probably
use some more features, to specify the desired behaviour.
If user *does* supply spring.cloud.function.stream.endpoint then it
is used and overrides all other possible routes.
The compiled functions implement that interface which means you can inspect
the signature of the method that created them and discover its
generic types.
Compiled functions always show up with no metadata, and you can only
guess what the types are from the bean definition. Probably we should
add more information to the bean definition if we have it when we
compile the function.
There is still a problem if user defines functions that are not of
Flux<String> (but that has always been the case).
Lambdas generally only deal with single values anyway, but for
consistency we should return similar results from a Lambda handler
as from an MVC handler in s-c-f-web.
If the request is a single value, we already know, so if we also
know that the function returned a single-valued type, then we can
render the single value, instead of an array with a single item.
See gh-36
These can be used to more reliably discover whether the user
has declared a function with flux types or "bare" POJOs. They
then pave the way to supporting single valued types in a special
way.
Also consolidate and simplify the logic in FunctionInspector