infinispan / infinispan/protostream
Support cascading/fallback SerializationContext
- Dominant language
- Java
- Stars
- 56
- Forks
- 39
- Avg merge
- 5h 36m
- Merged PRs (30d)
- 5
Description
## Background
Infinispan splits proto types across independent `SerializationContext`s that do not know about
each other (user / global / persistence — see
`infinispan: core/src/main/java/org/infinispan/marshall/protostream/impl/SerializationContextRegistryImpl.java`).
`org.infinispan.encoding.ProtostreamTranscoder` must handle payloads whose type is only known at
runtime (wrapped messages, canonical JSON with `_type`). Because no single context knows all the
types, it currently *guesses* the right context by trying the **user** context and, on
`IllegalArgumentException`, retrying the **global** context:
- `unmarshallCascading` — `infinispan: core/src/main/java/org/infinispan/encoding/ProtostreamTranscoder.java:133`
- `fromJsonCascading` — `ProtostreamTranscoder.java:147` (retries only if the message contains the literal `"Unknown type"`)
- `toJsonCascading` — `ProtostreamTranscoder.java:171`
- `getCtxForMarshalling` — `ProtostreamTranscoder.java:181` (manual `canMarshall` ladder)
This is exception-driven, duplicates the "user else global" logic across four sites, string-matches
an error message, and is hard-wired to these two contexts in this one class.
## Request
Support **cascading / fallback contexts** natively (tracked internally as `IPROTO-139`): a
`SerializationContext` can be configured with a fallback context that is consulted when a type
(marshaller or descriptor) is not found in the primary.
Proposed API (overloads in `org.infinispan.protostream.ProtobufUtil`):
```java
public static SerializationContext newSerializationContext(SerializationContext fallback)
public static SerializationContext newSerializationContext(Configuration configuration, SerializationContext fallback)
```
Implementation sketch: give `SerializationContextImpl` an optional fallback reference and make its
lookups (`getMarshallerDelegate` by class/object/typeId/typeName, `getDescriptorByName`/`ByTypeId`,
`canMarshall`, merged `getFileDescriptors`/`getGenericDescriptors`) resolve in the primary first,
cascade to the fallback on a genuine "not found", and throw only when both miss. Refactor the
internal resolution to return nullable rather than using catch-based control flow, so that
non-"not-found" errors (e.g. a type mapped to multiple protobuf types) are still propagated.
Putting the fallback on the impl (rather than a standalone wrapper context) means `WrappedMessage`,
`ProtobufUtil`, and the JSON reader/writer — which already cast to `SerializationContextImpl` — pick
up the cascade for binary and JSON (both directions) with zero changes at those call sites.
## Open questions
- **Type-id collisions:** a numeric `typeId` is only unique within one context; cascading
`getMarshallerDelegate(int)` across contexts with colliding ids could resolve wrongly. Decide
whether to restrict the cascade to name-based lookups or require non-colliding ids.
- Keep the relationship single-level (one fallback) for v1, or allow a guarded chain.
## Resulting Infinispan change (follow-up)
The registry would create the user context with the global context as its fallback, after which
`ProtostreamTranscoder` can drop the four `*Cascading`/ladder methods and simply use the user
context for all runtime-typed conversions.
A full design doc (alternatives, risks, test plan) is drafted at `docs/cascading-serialization-context.md`.
Contributor guide
Research direction
Read docs/cascading-serialization-context.md and the lookup methods in SerializationContextImpl, then inspect the proposed ProtobufUtil overloads and the referenced SerializationContextRegistryImpl and ProtostreamTranscoder entry points. Resolve the type-id collision and fallback-depth questions, implement primary-then-fallback lookup behavior without masking non-not-found errors, and verify that binary and JSON conversions inherit the cascade.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100