Repository navigation
Mosaic 0.6.0
Mosaic 0.6.0 release notes
Mosaic 0.6.0 brings named Tiles and execution tracing to a shared runtime with
Mosaic-owned Canvas construction and resource ownership.
Canvas and execution
Canvas is now a final Mosaic-owned class, created through canvas and
withLayer. It holds resolved bindings and inherited runtime configuration;
each Mosaic owns its request cache, batching, and execution state. mosaic-test
uses that same runtime with substituted Tiles and a test dispatcher.
Ordinary request layers that bind values stay small:
applicationCanvas.withLayer {
single(OrderKey) { orderId }
}.create().compose(OrderPageTile)Scope or close a Canvas when its local bindings own AutoCloseable resources.
Closing a child leaves parent resources open. Construction shares concurrent
binding resolution, detects dependency cycles, and cleans up successfully created
local resources on failure or cancellation in reverse creation order.
Named Tiles and observation
Use val OrderTile by singleTile { ... } to capture a property name. The same
syntax works with multiTile, perKeyTile, and chunkedMultiTile. Aliases retain
the first bound name and the original Tile instance; names do not change caching.
Ordinary = declarations remain valid and initially have no name.
The new mosaic-opentelemetry module adds
spans to your application's OpenTelemetry pipeline:
val applicationCanvas = canvas {
tracing { openTelemetry }
}Use tracing() with an already registered global provider, including a Java agent.
Spans use delegated Tile names when available, otherwise Mosaic single or
Mosaic multi. Shared work and additional batch callers appear as links; cache
hits create no spans. Context survives suspension and dispatcher changes.
Execution spans include attached child coroutines, even when a result is available
earlier. Observation failures are isolated from Tile results; each Mosaic retains
ownership of its shared work, caching, and batching.
Your application owns the SDK, sampling, exporters, and shutdown. Automatic
telemetry excludes keys, values, request identifiers, and exception contents;
delegated property names are visible as span names.
The runtime BOM now aligns mosaic-core, mosaic-test, and the optional adapter.
Adding the BOM alone does not install tracing.
Compatibility and migration
- Canvas source and binary break: external implementations, inheritance, and
delegation of the former Canvas interface are unsupported.MosaicCanvasis
removed. Replace direct implementation/construction withcanvasorwithLayer,
and recompile consumers against 0.6.0. CanvasBuilder/CanvasFactory construction
belongs to Mosaic; use the public DSL. - Kotlin: built with compiler and Gradle plugin 2.4.20, language/API level
2.4, stdlib 2.4.20, and coroutines 1.11.0. Runtime artifacts are tested
with Kotlin 2.3.0 consumers. Java 17 remains the runtime minimum; repository
builds and framework examples use JDK 21 and Gradle 8.14.4. - Analysis: requires exactly Kotlin compiler and Gradle plugin 2.4.20.
Rebuild dependency summaries generated with other compiler versions. Supported
Mosaic-owned delegated declarations preserve contracts; arbitrary delegates and
member-dependent Tile properties remain conservative analysis boundaries. - Delegate operators: Mosaic's member
provideDelegate/getValueoperators
take precedence over custom extension operators when consumers recompile. - OpenTelemetry: the adapter exposes API 1.66.0 and includes core. It does
not install an SDK or the optional Kotlin context extension in your application.
Runtime cost
A targeted JMH comparison with released 0.5.0, with tracing disabled, measured
the following synthetic runtime operations:
| Operation | 0.5.0 µs/op | 0.6.0 µs/op |
|---|---|---|
| Four-branch shared diamond | 5.6 | 5.7 |
| Four sibling coalescing consumers | 7.8 | 8.0 |
| 64-Tile chain | 27.7–28.4 | 28.9 |
Across comparison orders, the remaining timing differences were about
0.09–0.15 µs/op for diamond, 0.16 µs/op for sibling coalescing, and
0.6–1.2 µs/op for the 64-Tile chain. The diamond and coalescing fixtures
allocated about 1.2 KB/op and 1.6–1.9 KB/op more, respectively.
Cold trivial Tiles and cold 16-key batches had overlapping timing intervals.
Cost depends on graph shape; the technical guide includes width, depth, cache,
and complete execution-drain measurements.
These are elapsed microbenchmark timings, not application CPU/request or HTTP
latency. Timing and allocation were measured separately on JDK 21; reversed
comparison order confirmed the graph differences. See the
comparison methodology and results.
The application performance results describe their
documented source revision and were not remeasured for 0.6.0.
See the core guide,
analysis setup, and
changelog for usage and the complete release summary.
[0.6.0] - 2026-10-03
Added
- Delegated Tile naming with
val OrderTile by singleTile { ... }and equivalent
MultiTile factories. Aliases preserve the first name and the same cache identity. - Supported execution observation for actual Tile executions and MultiTile batches,
including caller context, shared-work relationships, and sanitized completion.
Observation failures are isolated from Tile results. - Optional
mosaic-opentelemetrymodule and Canvastracing()/tracing { openTelemetry }
DSL. Spans use delegated Tile names, propagate coroutine context, and link shared work.
The runtime BOM aligns the adapter alongside core and test libraries.
Changed
- Canvas is a final Mosaic-owned class built with
canvasorwithLayer.
External Canvas implementations andMosaicCanvasare removed; migrate to the DSL. - Canvas construction shares concurrent dependency resolution, detects cycles, and
cleans up local resources on failure/cancellation in reverse creation order. - Kotlin compiler and Gradle plugin move to 2.4.20 with language/API level 2.4;
runtime dependencies use stdlib 2.4.20 and coroutines 1.11.0. Runtime consumers
require Kotlin 2.3.0 or later; JVM 17 remains the runtime target. - Optional analysis supports exactly Kotlin compiler/Gradle plugin 2.4.20 and
recognizes supported Mosaic-owned delegated Tile declarations. Older compiler
summaries must be regenerated.