Release 3.0.0¶
See GitHub Release.
Viaduct 3.0.0 is a major release. The headline work is schema scopes declared in scopes.yaml and validated at build time, one ctx.ref(...) entry point for node and root-field references, a soft-by-default GraphQL Representational Type (GRT) getters, a Java Tenant API (beta release), and Java 25 support. It also includes early work on a new execution engine and @defer incremental delivery, both off by default.
Three changes affect every consumer's build regardless of what else they use:
- the Viaduct Gradle plugins now require Kotlin 2.2 or 2.3;
- tenant modules must be rebuilt with the 3.0 plugins;
- GRT getters
getX()now returnsnullon a data failure instead of throwing.
Start with Requirements and Breaking Changes below.
Requirements¶
- Java: 17 is the new minimum (support for Java 11 has been dropped), and the published bytecode still targets Java 17. Viaduct 3.0 is built and tested on Java 17, 21 and 25.
- Kotlin: the Viaduct Gradle plugins require Kotlin 2.2 or 2.3. Building for Java 25 needs Kotlin 2.3. Use a KSP2 release that matches your Kotlin version (KSP 2.3 uses standalone versions such as
2.3.7). - Gradle: 8.11 or newer; CI tests builds on 8.11 and 9.1. Java 25 needs Gradle 9.1 or newer.
Breaking Changes¶
Build and bootstrap — affects every consumer¶
- The Viaduct Gradle plugins require Kotlin 2.2 or 2.3 (16653620b) by @gokhan-ozgozen — Viaduct itself now builds with Kotlin 2.3.21, KSP 2.3.7 and Gradle 9.1. This commit carries no
!, but it is the change most likely to break a consumer build. See Requirements. - Rebuild every tenant module with the 3.0 plugins. Module configs generated by 2.0 fail at startup:
- every field and node entry must now carry
tenantMetadata(1a50aec92, 9b686122c) by @pclowes; - every config must declare an
apiName, and two configs with the same<tenantName, apiName>are rejected (9ffd1fd5c) by @kristileka; - a config file whose
versionis not1is rejected (0ea77aa07) by @kristileka. - Schema scopes are declared in
src/main/viaduct/scopes.yaml; theviaductApplication { declareScoping { } }DSL is removed (ad8aa6c09) by @geovannefduarte — move the DSL contents intoscopes.yamlwithversion: 1. Multi-document YAML, YAML aliases and empty named scope sets are rejected.SchemaScopingBuilderand theSCHEMA_SCOPES_DECLARED_TWICE/SCHEMA_SCOPING_DECLARED_TWICEerror codes are gone. - Schema files and module configs are loaded from build-generated resource indexes (7e8bd1805, 9e18ace23) by @pclowes — the application plugin writes
META-INF/viaduct/indexes/*.index, and the runtime loads only the resources listed there. Each indexed resource must appear exactly once on the classpath, and duplicate module-config contributors fail the build. Standard plugin layouts need no change..graphqlsfiles or module JSON added to the classpath outside the build must move into it. A missing index fails startup with an actionable error; there is no classpath-scan fallback. Supply schemas and module configs through the generated indexes, or pass them explicitly.
Stricter build-time validation¶
Each of these fails a build that 2.0 accepted:
- Type-level
@resolveron an object type that doesn't implementNode(RESOLVER_ON_NON_NODE_OBJECT) (20eee5ecb) by @gokhan-ozgozen; @namespaceTypeon a type that also declares@connectionor@edge(NAMESPACE_TYPE_HAS_CONFLICTING_DIRECTIVE) (a169f2bb1) by @alexanderuv;- Two fields whose generated accessors collide, such as
fooandfooOrThrow(527bad796) by @geovannefduarte; - A
@Resolverclass that doesn't extend exactly one generated resolver base. Indirect inheritance through an intermediate class is now allowed (85d2e3e15) by @catacraciun; - Required selection sets are disallowed on mutation resolvers (9755643c5) by @alexanderuv — mutation resolvers on the mutation root or on a reachable
@namespaceTypecan't declareobjectValueFragmentorqueryValueFragment. Callctx.query()orctx.mutation()insideresolveinstead; - A variable used inside a nested named fragment of a required selection set must be bound; otherwise bootstrap fails with
UnboundVariablesException(9a8e6f522) by @catacraciun; - A required selection set can't use a from-field variable in a
@skipor@includecondition (980b8b895) by @alexanderuv — a variable bound withfromObjectFieldorfromQueryFieldin theifargument fails bootstrap withInvalidVariableException. Select the value in the fragment and fetch the conditional data withctx.query()instead. Variables bound withfromArgumentor a variables provider still work; - A required selection set that applies a directive to a
@parentfield, or to an inline fragment or fragment spread that directly contains one, or that uses a variable anywhere beneath a@parentfield (49a9cab0b) by @alexanderuv; - With
scopes.yaml, an@scope(to:)name that isn't declared, or a declared scope set that produces an invalid schema (a324dedab) by @geovannefduarte; - Invalid
@scopeon type extensions that add no fields (922c023ef) by @geovannefduarte.
Generated types (GRTs) — Kotlin and Java¶
- The bare accessor
getX()now returnsnullinstead of throwing (f137387b2) by @geovannefduarte —getX()is now the soft accessor, andgetXOrThrow()is the strict one. Non-nullBoolean!/Int!/Float!fields now return the nullable boxed type, so Kotlin call sites that use the value in arithmetic or boolean contexts stop compiling, and code compiled against 2.0 fails withNoSuchMethodError. Call sites that need the old behavior must switch togetXOrThrow(). Call sites on already-nullable schema fields keep compiling but change behavior silently, so audit them by hand. Java GRTs follow the same model:getAmount()returnsDouble, andgetAmountOrThrow()returnsdouble. - The
getXOrNull()accessor form is removed from Kotlin GRTs (ba1a21601) by @geovannefduarte — rename call sites togetX(), which has the same soft behavior in 3.0. The API dump doesn't show this, because schema-specific generated classes aren't in it. - Java GRT reads now match Kotlin semantics (9d5b9ab42) by @catacraciun — reading an unselected or unset field raises
UnsetFieldExceptioninstead of returningnull. Anullon a non-null field, and malformed list or object values, raiseTenantUsageException. - Java GRT builders validate values (f4d90838a, 480a7663c) by @catacraciun:
- a setter that receives a wrong scalar class, an invalid enum value, a GlobalID for the wrong type, or a
nullfor a non-null field throwsTenantUsageException; build()throws for missing required fields and@oneOfviolations;- list values are stored as unmodifiable copies.
- Java resolvers for
@idOfand Node ID fields returnGlobalID<T>instead ofString(d940dd53f) by @catacraciun - Java object GRTs no longer generate a
Fields.<field>constant for@backingDatafields (930382ac8) by @catacraciun — read backing data withObjectBase.get("field", Backing.class).
Tenant API — resolver context¶
nodeRefis nowref(e128ccc48, 4ec3666ff) by @alexanderuv —ResolverExecutionContext.nodeRef(GlobalID)and the KotlinnodeRef(localId: String)extension are removed in both the Kotlin and Java APIs. Callctx.ref(...)with the same arguments.rootFieldRefis replaced byctx.refwith a generated root field call (bc4a879d9, 6ca3d04b9) by @alexanderuv — for example, Kotlinctx.rootFieldRef(Query.Fields.product, args)becomesctx.ref(Query.product { ... }).RootFieldCall.resolveis replaced byfield()andarguments(context), so hand-writtenRootFieldCallimplementations must be updated.- The string-based
query(String, …)andmutation(String, …)overloads are removed from the Kotlin API (bcbf4a12e) by @kristileka — usequery(QueryFromAnnotation, …)andmutation(MutationFromAnnotation, …). - Mutation contexts no longer expose query or object values:
- Kotlin mutation contexts lose
getQueryValue()(a46dc0792) by @alexanderuv; - the Java
MutationFieldExecutionContextno longer extendsFieldExecutionContext(e6dcb1e14) by @alexanderuv.
Read data with ctx.query(...) inside resolve.
- In the Java API, ctx.mutation() works only in mutation field resolvers (a7787b34e) by @catacraciun — calling it from a query, node or object-field resolver throws TenantUsageException.
- ResolverExecutionContext.selectionsFor(type, selections, variables) is removed (9139e4ed4) by @amity177 — declare reads as resolver dependencies, or use named operations.
- The selection-construction surface of SelectionSet is removed (a6c0aaa2a, 4116a184d, de300569b, 8f2ce9602, c69d773c7) by @amity177:
- removed: SelectionSet.type, isEmpty(), selectionSetFor(Type) and toFragment(), plus the OutputSelectionFragment class;
- a custom SelectionSet passed to framework batching must implement InternalSelectionSet.
- New abstract members for code that implements tenant API interfaces itself, such as test fakes:
- SelectionSet.selectedFieldCoordinates() (c3f681279) by @alexanderuv;
- SelectiveNodeExecutionContext.ownedSelections() (afe33183d) by @fireboy1919.
- isPresent(field) is now true for an omitted input field that has a schema default (2731f3c88) by @catacraciun — Java input getters also return the schema default. Code that used isPresent to tell a client-sent value from an applied default must compare against the default instead.
- Input getters and argument wrappers return programmatic defaults (cdfc33bbd) by @catacraciun — in 2.0 they threw or dropped the default.
- viaduct.api.fetchOrNull and fetchOrDefault are now @InternalApi (b28ba31e1) by @catacraciun — Kotlin callers get an opt-in warning, which -Werror turns into an error.
- Selective resolvers are temporarily disabled in the Java tenant API (8d6e7c90b) by @catacraciun — @resolver(isSelective: true) on a Java-resolved field or node fails codegen and bootstrap. Remove it, or keep those resolvers in Kotlin.
Service API¶
ViaductBuilder.withScopedSchemasFromSdlis removed (c6b0ba2fe) by @gokhan-ozgozen — 2.0's notes introduced it as the replacement forwithSchemaConfiguration. UsewithScopedSchemas(...), withSchemaScopeInfo.fromResources()to read the scoped schemas declared inscopes.yaml.withScopedSchemasrejects an empty list, and the scope-definition types move (93ac16f77) by @geovannefduarte — registering no views used to build successfully and then answer every request withSchema not found.SchemaScoping,SchemaScopingValidatorandScopingErrorCodesmove fromviaduct.service.api.scopingtoviaduct.scoping.- New
FlagManager.Flagsentries (ba3865e57) by @rstata — a customFlagManagerthat returnstruefor every flag now fails engine construction, becauseENGINE2_ENABLEDandENGINE2_BATCHINGmust be off on the default engine.ENABLE_CACHE_KEY_LOOKUP_PARTITIONINGis deprecated, and partitioning is always on (81f0c0512) by @njlynch. - Resolver error reporters receive
ResolverOutputMissingFieldException(aaa998ebf) by @fireboy1919 — this happens whenever a requested field is missing from a resolver's output. The newENABLE_RESOLVER_OUTPUT_MISSING_FIELD_ERRORSflag also turns it into a GraphQL error (VIADUCT_RESOLVER_OUTPUT_MISSING_FIELD).
Test fixtures (com.airbnb.viaduct:test-fixtures)¶
RootFieldRefStuband therootFieldRefValues/rootFieldRefResultsinputs are removed (f1f62aab6, e5906d370) by @alexanderuv — assert the references a resolver creates withReferenceSpy.- The mock execution contexts' constructors gain a
referenceSpyparameter beforeownedSelectionsValueandcaller(e5906d370) by @alexanderuv — pass trailing arguments by name. - Mutation mocks and specs no longer accept
queryValue(2acd5b6c9) by @alexanderuv — supply query results throughcontextQueryValues. - Classpath resolver scanning is removed (d2dcb1c6f) by @pclowes —
ClassGraphScanner,TenantResolverClassFinder,TenantPackageInfoandfindResourcePathsMatchingare gone. The feature-app test contracts no longer validate resolver completeness by scanning. - The jar no longer bundles JUnit or ClassGraph (5d73441bd, 9e18ace23) by @geovannefduarte, @pclowes — 3.0.0-rc.1 bundled JUnit Jupiter API 5.11.3, which 2.0.0 did not. Declare
junit-jupiter-apiin your test dependencies, as 2.0.0 already required.
Engine SPI — affects advanced integrators¶
- The
TenantAPIBootstrapperlane is removed (a73e3ac81, cf9919915) by @kristileka —StandardViaduct.Builder.withTenantAPIBootstrapperBuilder(s)andwithNoTenantAPIBootstrapperare gone. Provide tenants through module configs andwithTenantModuleInjectorFactory. - The Java classpath-scanning bootstrapper is removed (db0dcf71d) by @catacraciun —
ModuleBootstrapper,DefaultResolverClassFinder,JavaTenantAPIBootstrapperandResolverClassFinderare gone. Java resolvers load from the registry themodule-javaplugin generates at build time. TenantModuleis removed (7f7bde034) by @pclowes — resolver attribution comes from the generatedtenantMetadata.- The engine schema type
ViaductSchemais renamedEngineSchema(b5444c026) by @gokhan-ozgozen — this changes the deprecatedViaductBuilder.withCheckerExecutorFactoryCreatorand theCheckerExecutorFactory/ExecutorFactorySPIs. - Other engine-API removals and moves:
ObjectEngineResultandResolveSelectionSetOptions.targetResultare removed (93f54eeaa) by @rstata;- the execution-registry config types move to
viaduct.bootstrap(c19ab6a6f) by @kristileka; SelectionsParser.parselosesknownFragments(300e99eeb) by @kristileka;Engine.completeSelectionSetis removed (609a6a728) by @rstata.
Experimental — x/remoteresolvers, not covered by the API stability contract¶
- The remote-resolver wire encoding is now versioned (7fc43a5b0) by @cetinsahin — build the RRS and the RRP from the same Viaduct version.
Features¶
Schema scopes¶
- Scopes are declared in
scopes.yaml, and every declared scoped schema is built and validated during the build, with all failures reported at once (ad8aa6c09, a324dedab) by @geovannefduarte. - The build hands the declared scopes to the runtime as a manifest, and
SchemaScopeInfo.fromResources()returns them (93ac16f77) by @geovannefduarte.
Java tenant API¶
- Stability annotations: every public Java API type carries
@StableApi,@ExperimentalApior@InternalApi(c8a0913bf) by @catacraciun, and the stable surface is checked for binary compatibility (#436) by @geovannefduarte. - Location: the implementation moved from
core/x/javaapitocore/javaapi(70423b54b) by @catacraciun. Packages and published coordinates are unchanged. The API reference moved from/apis/x-javaapi-api/to/apis/javaapi-api/. - Generated types now match Kotlin: Java GRTs generate the same accessors as Kotlin (9d5b9ab42),
toBuilder()on object and input GRTs (cd4028da2), and dynamic@backingDatareads (930382ac8). Code generation honors custom root type names (8f45c84e3). All by @catacraciun. - Resolver features:
- field batch resolvers can return a per-item value, null or error through
batchResolveWithErrors(87f886c8e); - typed
GlobalID<T>for ID fields (d940dd53f); @TenantBootstrappersupport (97025acd1);- non-blocking
fetchOrNull/fetchOrDefaulthelpers (b28ba31e1).
All by @catacraciun.
- Gradle: the module-java plugin runs the Java registry annotation processor and packages the module config, so Java modules bootstrap without classpath scanning (6345cc115) by @kristileka.
- Demo: a standalone Java demo application, demoapps/starwars-java (4e05cd91b) by @catacraciun.
Resolver context and references¶
ctx.ref(...)is the single entry point for lazy references to nodes and root fields:ctx.ref(GlobalID)andctx.ref(localNodeId)(d9828a499) by @alexanderuv;- generated
RootFieldCallfactories on the root query type and every eligible namespace field (4ca5b19ae, 23b0a3d14) by @alexanderuv. - Field resolver contexts expose the calling resolver as
caller. It is informational and must not be used for authorization (ba07c27e2) by @alexanderuv. - Generated types add
getXOrThrow()next togetX()(527bad796) by @geovannefduarte. ReferenceSpyasserts the references a resolver creates (e5906d370) by @alexanderuv, and the mock harness supports@GraphQLOperationqueries and mutations (ae6da2a78) by @kristileka.
Selective resolvers¶
- Selective resolvers can read the selections they own with
ownedSelections()(afe33183d) by @fireboy1919. - Experimental batching helpers in
viaduct.api.batch, andSelectionSet.selectedFieldCoordinates()(c3f681279) by @alexanderuv. - A
FieldSelectivityProviderSPI (75641a72f) by @jbellenger. - Documentation and a Star Wars demo of selective field and node resolvers (b7b444b15, 74f0782db) by @jbellenger.
Build and Gradle plugins¶
- Java 25 support: Viaduct is tested on Java 17, 21 and 25, and the demoapps run on all three (#437) by @geovannefduarte.
- Viaduct builds with Kotlin 2.3.21, KSP 2.3.7 and Gradle 9.1 (16653620b, 00230ca63) by @gokhan-ozgozen.
- Schema and module-config loading is owned by the build (7e8bd1805, 9e18ace23) by @pclowes.
- New
com.airbnb.viaduct.gradle:metamodulelibrary, applied by the module plugins (b5b5115b7, a94251ea3) by @gokhan-ozgozen: - it validates that each module is declared in the application topology;
- it lets module-extension plugins contribute schemabase definitions;
- identical contributions are deduplicated, and conflicting ones are reported with their sources.
- Generated interfaces carry both native JVM default methods and the legacy
DefaultImpls, so consumers link with either layout (1fa7c7da9) by @fireboy1919. - Routine KSP processor messages moved to verbose logging (f238f49eb) by @njlynch.
Schema and engine¶
@parentaccepts several compatible producer fields (c0032ed7f).- A temporary field-level shadow-execution hook for internal use (85ca12785) by @andimarek, and callers can fork isolated shadow execution state (c8e62db8e) by @amity177.
DataLoadersubclasses can customize internal loader creation (18a660296) by @bhavanapallempati.memoizeaccepts non-concurrent caches (a855babbb) by @gummybug.
New execution engine and @defer — early work in progress¶
Both are off by default and are not ready for production use.
- A new execution engine is selected only when
FlagManager.Flags.ENGINE2_ENABLEDis on (ff34cb070, ba3865e57) by @rstata. It supports Viaduct's extended scalars (ba87d1628) by @andimarek, plus a series of performance improvements (e38d04431, 9e80ec47f, 5edbd7eab, 56ac359eb, 3866ea733, 4cff74838, 0c11c65b3, 2c597944a, 5f0a222d8, 2d91c4273) by @rstata. Thestarwars-javademo turns it on (3719e6ea0) by @catacraciun. @deferincremental delivery, behind the newENABLE_INCREMENTAL_EXECUTIONflag (bada0c9bc). With the flag on, the engine returns deferred payloads in the June 2023 incremental response format (ec0fe07a0), and each execution group completes independently (83779a540, b7a1e0659), all by @jbellenger. Callers that call the engine directly must smart-cast itsExecutionResulttoIncrementalExecutionResultto read incremental data; this is temporary until graphql-java supports the format. The groundwork:- defer usage collection and execution plans (c209bf224, e32ed2b97, 3e45fbace);
- deferred work tracking (2d97c3bc1, d6e3bffaa, 8243066bf, b7f3713c0);
- EnsureID, WorkGraph and WorkQueue (b1fba6a23, 3d295b01e, f1e3ca1c1);
- a built-in
@deferdefinition (c13908fe3).
Remote resolvers (experimental)¶
ctx.query()andctx.mutation()callbacks work across JVMs (5cd9fbfe8) by @cetinsahin.- Response context from remote resolvers (57b0ad316) by @junjinp.
- An opt-in streaming transport for node resolvers (9ce37b455) by @vickeyyeh.
- Client interceptors on the RRS gRPC channel (f2c4e6578) by @vickeyyeh.
- Dispatch and execution instrumentation SPIs, and remote-resolver metrics and error classification (981d39d6f, 00cea8a86, 3b2327ce0, 00fff5710, 463d0197b, f231d6ca0, 002889d63, 1228c8c24, b90442590) by @vickeyyeh.
Bug Fixes¶
Execution and engine correctness¶
- Allow sibling progress during composite list traversal (03e7b3cc5) by @skevy
- A selective resolver that reads its own object while it is still loading no longer deadlocks (e59bd3b7b) by @jbellenger
- Root field references resolve in the same object tree, and node resolvers that return them no longer hang (c57084bbf, 92b8a28c4) by @gummybug, @jbellenger
- A selective node reference selected only by
id/__typenamenow always resolves (e3b1c4165) by @alexanderuv - Respect parent-supplied values during selective resolution (d6f6d6a0a) by @alexanderuv
- Preserve field argument values during rematerialization (c32ea44e1) by @alexanderuv
- Bind operation variables in materialization plans (abb60562a) by @alexanderuv
- Stop dropping
... on Typefragments when a resolver is re-run (3a55747e0) by @alexanderuv - Unwrap parent-managed values selected from materialized lists (76c5647aa) by @gummybug
- Keep filtered field ASTs aligned with query plans (f5a17d851) by @gummybug
- Attribute conditional exclusions to the types a selection reached (80f5b9c96) by @geovannefduarte
- Preserve parent traversal in selective refills (4d081cb46) by @alexanderuv
- Preserve tenant materialization errors (0b8b1c294) by @jbellenger
- Misc selective field fixes (29d36102b) by @jbellenger
- Fix selective node materialization interop (5218c1dd7) by @jbellenger
- Fix materialization variable resolution (6d8e2aacb) by @jbellenger
- With materialization on, an error from a selective node resolver is stored on the result instead of failing the request with
InternalEngineException, matching the behavior without materialization (d5c8e840e) by @gummybug - Convert Classic resolver backing objects during materialization (3f1be62c5) by @gummybug
- Follow named fragments when extracting checker variables (17823aa85) by @andimarek
- Fail the batch instead of hanging when the schedule callback throws (d391f4799) by @vickeyyeh
- Populate field variable definitions during bootstrap (5af014fa6) by @kristileka
- Wire tenant module metadata into Modern resolver metadata (18fbb4157) by @vickeyyeh
- Reuse immutable execution registry config snapshots (b324765ea) by @pclowes
Java tenant API¶
- Preserve nested list shape in specialized Java GRT conversions (778e62a97) by @catacraciun
- Make GlobalID equality and hashing structural (6945bffbb) by @catacraciun
- Restore batch invocation attribution (02ffb4a98) by @catacraciun
- Use resolver coordinates for VariablesProvider arguments (fa9b0163d) by @catacraciun
- Allow resolvers to inherit generated resolver bases indirectly (85d2e3e15) by @catacraciun
Service and GraphiQL¶
- GraphiQL loads again (45692c718) by @geovannefduarte — since 2.0.0 the bundled page imported a JavaScript file that was never shipped, so it stayed on "Loading…", and the Global ID plugin couldn't load. Babel is now pinned to 8.0.7 with an integrity check.
Schema, codegen and build plugins¶
- Support enum values that are language keywords (475c976f1) by @alexanderuv
- Preserve descriptions when converting schemas to GraphQL Java (f482e4ed4) by @pclowes
- Preserve runtime schema metadata (93f45a5e2) by @pclowes
- Make file source names platform-independent (4428ada91) by @geovannefduarte
- Schema validation rules match module partition paths on Windows (ce689a694) by @geovannefduarte
- Hide
@bypassPolicyCheckfrom client-facing schema views (12f0c2b83) by @andimarek
Remote resolvers (experimental)¶
- Support unary remote resolver callbacks across processes (5cd9fbfe8) by @cetinsahin
- Preserve unary callback execution errors (019d02f10) by @cetinsahin
- Carry nested object type identity over the wire (7fc43a5b0) by @cetinsahin
Performance Improvements¶
- Prevent a single deeply nested polymorphic query from exhausting the heap while mat constructs its field-coverage KeyTree (5a5e7561a) by @gummybug
- Avoid repeated copying when merging selection sets (ba73f44e6) by @gummybug
- Avoid including multiple occurrences of duplicated selections in CollectedField (40cc0f49a) by @gummybug
- Avoid traversing selection trees when hashing selectors (ac33dd577) by @gummybug
- Parent completableDeferred directly to the request supervisor (9895e1bbf) by @viaduct-maintainers
- Partition data loader custom cache-key matching, and make the partitioning unconditional (4d25b4d0d, 29731b19b, 81f0c0512) by @njlynch
- New engine: compact parent demand, reuse materialization templates and selection forests, reduce cycle-check work, consume compliant resolver outputs directly, improve demand closure scaling, reduce selection merging and demand transformation overhead, remove hot-path invariant validation, and reuse normalized selections (56ac359eb, 5edbd7eab, 9e80ec47f, 3866ea733, 4cff74838, e38d04431, 0c11c65b3, 2c597944a, 5f0a222d8, 2d91c4273) by @rstata
Documentation¶
- Document object GRT
toBuilder()(8dfd66c91) by @gummybug - Document selective resolvers (b7b444b15) by @jbellenger
- Document
ctx.reffor root field references and node references (cbd046ea9, 3ab51ecc5, 63f2c732e) by @alexanderuv - Document directly returning GRTs from required selection sets (811fc83d2) by @gummybug
- Document that from-field variables can't be
@skip/@includeconditions (2253d7790) by @alexanderuv - Add Java developer documentation: quickstart, foundations, setup and Star Wars tutorials, advanced guides, and service integration (91e8e5113, c482c47e7, 0b76c91e9, 73427e38a, 5f7d20d03) by @catacraciun
- Update the supported Java, Kotlin and Gradle versions (#438) by @geovannefduarte
- Update the roadmap for 3.0 (#442) by @geovannefduarte
- Record the Java mapping domain deferral (3e4e85ef8) by @catacraciun
- Clarify new engine names and source references (2dbebb5d7) by @viaduct-maintainers
- Update
AGENTS.mdfor bootstrapping (ed8e26cf8) by @kristileka - KDoc updates (9ce0849f7) by @andimarek
- Add 2.0.0 release notes post (#406) by @geovannefduarte
Testing¶
- Verify mixed Kotlin and Java Viaduct Gradle modules in one application topology (a31022dc0) by @catacraciun
- Cover selective node, selective field and parent field interactions (50dcf6c54, dfaa3235b) by @alexanderuv
- Add coroutine context contract (d2282c258) by @rstata
- Share feature test harness through StandardViaduct (e716e6495) by @rstata
- Support tenant provider variables in numbered resolver families (ec641cecb) by @rstata
- Reset Resolution overhead baseline and feature coverage (a7d5b215d) by @rstata
- Isolate large-schema round-trip tests (327f3b113) by @rstata
- Use explicit values in mock field fixtures (7ef2f402f) by @rstata
- Add a StandardViaduct engine comparison benchmark (560fe7a76) by @rstata
- Derive reproducible schema seeds from content hashes and a seed variant (12e9aa865) by @kristileka
- Generate the classdiff test schema from the arbitrary schema generator, with a pinned seed and case-only name dedupe (58a726186, c39ca87bb, 71981a6e9) by @kristileka, @jbellenger, @geovannefduarte
- Layer Viaduct directive shapes onto the arbitrary schema generator (fc6d94726) by @kristileka
- Replay generated resolver contract witnesses, list-deepening and mutations, and store property-test suites (bf53d82ac, 2a7833598, 3cba206ea) by @kristileka
- Generate namespace types, root field references and a coordinate index in the arbitrary schema generator (dfc8e8e79, d15f297c0, c9e325b75) by @jbellenger
- Add an isolated Java resolver test fixture (62fed5e31) by @catacraciun
- Move GraphQL-independent arbitrary helpers to
viaduct.arbitrary.common(019b12a34) by @kristileka - Measure maybeDelay with virtual time (d5f538c81) by @geovannefduarte
- Bound the async fetch, not mockk setup (#422) by @geovannefduarte
- Resolve TestKit fixture jars from a synced repo (#417) by @geovannefduarte
- Stop testParallelMap failing under CI contention (3f93f0f94) by @geovannefduarte
- Make mixed unions assertions order-independent (5c0c110ca) by @geovannefduarte
- Compare runtime2 source paths with forward slashes (#434) by @geovannefduarte
- Make runtime2 tests pass on Windows (#440) by @geovannefduarte
- Register the scoping manifest task without the deprecated create API (46a828450) by @geovannefduarte
- Stabilize type-checker coverage in CI (6c58a9e29) by @rstata
- Observe fresh-thread failures with FutureTask, limit invalid-schema diagnostics to exceptions, and catch expected concurrent-write failures (f02ac2df9, c86d78496, 0fabde072) by @viaduct-maintainers
Refactoring¶
- Move Java API implementation to core/javaapi (70423b54b) by @catacraciun
- Share Kotlin and Java input type construction, required selection set dependencies, annotated operation preparation and node batch execution (fbb6f91bc, 9a8e6f522, 8b7f5cead, cc0e63d46) by @catacraciun
- Introduce
FullSchemafor the complete engine schema while keeping scoped views asEngineSchema(872ac4897) by @gokhan-ozgozen - Rename the engine
ViaductSchematoEngineSchema(b5444c026) by @gokhan-ozgozen - Build the RRS schema and executors as an instance-owned runtime (38af9473a) by @njlynch
- Remove remote resolver proxy factory registry side effects (5bbe8838d) by @njlynch
- Read materialized paths and coverage through the field reader, and make materialized field reads configurable (a675bd66f, 3676d91c4) by @alexanderuv
- Share data fetcher result transformation (6225ba54f) by @alexanderuv
- Collapse fetchObject/fetchObjectSerially into one serially-flagged method (43b4c7081) by @alexanderuv
- Rename nodeRef call sites to ref (862a289d1) by @alexanderuv
- Introduce ExecutionMode, CollectFields.Result and other CollectFields refactorings (012a2284e, fdc18c39f, 8258a42c1, bba534179) by @jbellenger
- Introduce incremental variable definition plumbing (c002edb18) by @rstata
- Add tenant-local fields to internal scoped schema construction (37a643da9) by @gummybug
- Store FieldCompleter in Constants (79ddf0dc1) by @jbellenger
- Preserve empty KeyTree branches (ed6f40bfa) by @jbellenger
- Encapsulate schema metadata with typed holders, and add a programmatic schema builder with filtered copies and type roles (4b81f93fe, a788f0497, 457b15861, a798d09a7) by @rstata
- Add
neverHasArgsfield metadata to the internal schema model (abd53f56c) by @rstata - Internalize ObjectEngineResult and checker result completion (93f54eeaa, 609a6a728) by @rstata
- Separate resolver capability from dispatch policy (92a40bec0) by @viaduct-maintainers
- Create
shared/bootstrapfor the execution-registry config model (c19ab6a6f) by @kristileka - Remove
knownFragmentsfrom SelectionsParser (300e99eeb) by @kristileka - Give every execution registry configuration an explicit
<tenantName, apiName>identity (9ffd1fd5c) by @kristileka - Move callers onto the file-based bootstrap path, then delete the second bootstrap lane (aa130706f, cf9919915, a73e3ac81) by @kristileka
- Generalize the file-based classic tenant-module-config to all classic resolver directives (6b1eda4d0) by @kristileka
- Rename the internal GRT accessor entry points (40041ea6a) by @geovannefduarte
- Use getFooOrThrow in engine tests, tutorials and the starwars demoapp (4cce8bf9f) by @geovannefduarte
- Move tenantFromLocation to ModulePartitionPaths (#426) by @geovannefduarte
- Remove unused internal schema tenant-path helpers (2044ee871) by @geovannefduarte
- Remove unused ViaductModernInstrumentation interface (62c1f63a6) by @andimarek
- Separate VSchema and ViaductSchema generators (c716d9264) by @jbellenger
- Add input and output value type aliases (bfbc03bb0) by @gokhan-ozgozen
Build System¶
- Test on Java 25 alongside 17 and 21 (#437) by @geovannefduarte
- Validate the Java API's binary compatibility (#436) by @geovannefduarte
- Upgrade Viaduct OSS to Kotlin 2.3.21, KSP 2.3.7 and Gradle 9.1 (16653620b) by @gokhan-ozgozen
- Prepare Gradle build and tests for Gradle 9 and Kotlin 2.x (00230ca63) by @gokhan-ozgozen
- Run tests on the matrix JDK (#432) by @geovannefduarte
- Apply static analysis to four unlinted modules (#429) by @geovannefduarte
- Add the Java linting stack (f58d9d643) by @catacraciun
- Normalize bytecode comparisons across Kotlin compiler versions (38a650bfd) by @freetheinterns
- Replace subprojects{} scanning with BuildService self-registration and configuration sharing (302618eb8, bb9cc4193, f55a9f04d, ac3a74d75) by @gokhan-ozgozen
- Run standalone checks after included builds (1b2aa7966) by @fireboy1919
- Add Artifactory mirror to root plugin settings (0857f6bad) by @gokhan-ozgozen
- Restore stock Gradle 9.1.0 wrapper jar and scripts (#435) by @geovannefduarte
- Pin Spotless line endings to LF (#410) by @geovannefduarte
- Delete the orphaned bom module (#423) by @geovannefduarte
- Index Java and Kotlin golden resources to remove an unnecessary ClassGraph dependency (6d91d5eb5, 1fbae1553) by @pclowes
- Check that the test-fixtures jar never bundles JUnit (5d73441bd) by @geovannefduarte
- Use one djlint ignore list for every docs check (#441) by @geovannefduarte
Continuous Integration¶
- Drop the Java 11 matrix leg (#431) by @geovannefduarte
- Introduce a CodeArtifact mirror for build artifacts (#424) by @gokhan-ozgozen
- Derive the artifact probe list from the build (#419) by @geovannefduarte
- Validate every demo app's pinned Viaduct version (1e10d004e) by @geovannefduarte
- Render BREAKING CHANGE text in release notes (#433) by @geovannefduarte
- Label retry alerts with the failure cause (#427) by @geovannefduarte
- Accept only Gradle task paths in CI alerts (#428) by @geovannefduarte
- Retry a failed nightly once before alerting (#425) by @geovannefduarte
- Retry a failed run once before alerting (#415) by @geovannefduarte
- Run coverage only on schedule and dispatch (#418) by @geovannefduarte
- Run Copybara on Java 25 (#416) by @geovannefduarte
- Report every matrix leg, key concurrency per entry point (#413) by @geovannefduarte
- Stop discarding matrix and task failure evidence (#411) by @geovannefduarte
- Stop discarding Windows nightly failure evidence (#409) by @geovannefduarte
- Make demoappsStandaloneTest work on Windows (#408) by @geovannefduarte
- Cache demo app Gradle distributions to stop repeat downloads (#407) by @geovannefduarte
- Never cancel main CI runs to protect the shared Gradle cache (#402) by @geovannefduarte
Chores¶
- Mark the materialized field reader as for Airbnb use only (5bce92343) by @alexanderuv
- Add a comment documenting materialization behavior (c52294b94) by @gummybug
- Fail module config assembly on selections of forbidden-directive fields, behind an opt-in CLI flag (c72b78625) by @viaduct-maintainers
- Pin the seed used for some arbitrary schema generations (c39ca87bb) by @jbellenger
- Dumpable field references (a9eca264c) by @jbellenger
- Fix nullable reference field generation (b94df0308) by @jbellenger
- Classify long-running central-schema reflection tests correctly (00c3638b8) by @pclowes