cashapp / redwood

Multiplatform reactive UI for Android, iOS, and web using Kotlin and Jetpack Compose
https://cashapp.github.io/redwood/0.x/docs/
Apache License 2.0
1.6k stars 70 forks source link

Schema Versioning #37

Open swankjesse opened 3 years ago

swankjesse commented 3 years ago

Schemas change over time. We need to design a safe way for composers and displays to interop safely if their schemas are on different versions. We should also consider tools to help prevent unexpected incompatible schema changes.

I recommend we enforce that the composer code is never older than the display code. Supporting forwards and backwards compatibility is way harder than just backwards compatibility. Developers are already familiar with only backwards compatibility; servers are never older than their clients. If the composer code is too old, we get new code by either updating dependencies (build time) or downloading (runtime).

I recommend we require explicit schema versions. I think a single integer like Android API versions should be enough. I don’t expect we’ll ever want to change schema version 3 after schema version 4 is created. We can make the schema version an attribute of the @Schema annotation, and build some process or mechanism to remind people to bump this.

I recommend we make the display’s version available to the composer so it can fall back. For example, a composer could emit a stock price to a TextLabel if the display doesn’t support a StockChart node.

To prevent unexpected schema versions we could generate a JSON representation of the schema as a project resource, generated when we generate code. The Gradle plugin could check whether the JSON representation of the current project is compatible with another version. We do this with japicmp in Okio and it’s saved us enough times to be worth the investment.

JakeWharton commented 3 years ago

I would not choose JSON since it diffs quite poorly. Simple plain text with indents (similar to metalava in AndroidX or the binary validator by Kotlin) or YAML/TOML diff well in comparison.

Otherwise this sounds exactly like what I had in mind.

JakeWharton commented 2 years ago

Ideas from meeting with Eric:

Note that this is different than runtime querying but not entirely separate from it as runtime querying should also be considered a valid conditional to suppress the check.

JakeWharton commented 2 years ago

This also requires no version annotations directly in the schema. Instead for each version you update the schema manifest which adds all new widgets and the associated version but retains all the old version history.