Migration guide
To see the biggest differences please consult the changelog.
In version 2.3 (Not released yet)
HTTP Endpoint and WebSocket source metadata
!1204 removes Kafka record metadata
from #inputMeta for HTTP Endpoint, WebSocket Client and WebSocket Server sources. The removed fields are
headers, key, topic, partition, offset, timestamp, timestampType and leaderEpoch.
Only #inputMeta.httpHeaders remains, containing forwarded HTTP headers with the _http_ prefix removed.
- Replace HTTP header expressions such as
#inputMeta.headers['_http_content-type']with#inputMeta.httpHeaders['content-type']. Other Kafka record headers are no longer exposed. - Migration 504 clears the Event time parameter automatically when it contains exactly the former default,
#inputMeta.timestamp. Custom Event time expressions remain unchanged. The new default is empty: the runtime uses the upstream record timestamp, falling back to the current time if none is available.
Ordinary Kafka sources continue to expose Kafka metadata through #inputMeta.
The Configurator requires Integration actions
Reading it takes Integration.View, saving Integration.Create or Integration.Edit, deleting Integration.Delete;
secrets are masked as ****** without Integration.Edit. The users/rules configuration cannot grant these
actions, so there the Configurator is admin-only; grant them under RBAC.
The Topics tab requires Topic actions
Listing and reading topics takes Topic.View, previewing their messages Topic.ViewMessages, creating one
Topic.Create, changing retention or the schema Topic.Edit, deleting one Topic.Delete. Grant
Topic.ViewMessages only to those who may see production records. The users/rules configuration cannot grant
these actions, so there the Topics tab is admin-only; grant them under RBAC.
A webhook source's actions take: generating its endpoint Topic.Create (admin-only under users/rules), testing a
WebSocket forwarder Scenario.Edit (Write), sending a data sample Scenario.Test (Deploy) in the scenario's
category. The sample goes to the topic of the source as saved, so save the scenario before sending one.
The MCP tab requires MCP actions
Listing and reading MCP definitions, the scenarios available as tools, a tools preview and a server's machine access take
MCP.View; creating a definition MCP.Create, changing one MCP.Edit, deleting one MCP.Delete. Generating and
revoking a server's tokens takes MCP.Edit and, as before, RBAC.Manage. The users/rules configuration cannot grant these
actions, so there the MCP tab is admin-only; grant them under RBAC.
REST API changes
-
!1469
categoriesofGET /api/useris an object instead of a list: the visible categories grouped by the processing modes of the scenario types configured in them, e.g.{"Unbounded-Stream": ["Category1", "Category2"]}. For the former list, take the distinct categories of all its values. -
!970 Custom nodes with dynamic outputs, added fields:
outputs(list of output names, main output first, ornull) in the node validation response and in eachnodeResultsentry of the scenario validation response,dynamicOutputs(boolean) in theedgesForNodesentries of the component definitions.
-
!1264 The
create-kv-namespaceanddelete-kv-namespaceactions ofPOST /api/custom/nodes/{scenarioName}/actionsandGET /api/custom/nodes/actions/kv-namespace/metadataare removed. Use/api/custom/kv-store-management/stores/{storeId}/namespacesinstead (list, get, create, delete), withstoreIdfromGET /api/custom/kv-store-management/stores; it needs an admin account. To keep managing namespaces, put thekv-store-managementDesigner extension (extensions/kv-store-management/*) on the DesignerCLASSPATHand add the Key-Value Store tab totabs:{id: "key-value-store", title: "Key-Value Store", type: "Remote", url: "nuEnterpriseKvStoreManagement/tab@/static/kv-store-management/remoteEntry.js", adminOnly: true}.examples/installationhas both. The new API takes the value schema only asjsonSchema; it does not usetypingResult,categoryorprocessingType. -
!1403
allowedProcessingModesof the elements ofGET /api/componentslists the processing modes of the scenario types the component is available in, intersected with the modes it supports, instead of every mode it supports. A component available only in streaming scenario types returns["Unbounded-Stream"]where it used to return all three modes.
Code API changes
-
!970 Custom nodes with dynamic outputs:
DynamicComponent.FinalResultsgained a fourth field,outputs, so a positional pattern match needs an extra_. The field defaults toNone, and component jars that createFinalResultsor callFinalResults.forValidationkeep working without recompiling; only ones that pattern match onFinalResultsor call itscopyneed recompiling.CustomComponentSpecificDatagained a fourth field,hasDynamicOutputs, andValidationPerformeda fifth,outputs- positional pattern matches need an extra_.
-
!970
AdditionalInfoProvider.nodeAdditionalInfogets the scenario'sMetaDataalong with the node:nodeAdditionalInfo(config)(metaData, node). Add the parameter to your providers. -
!1423
DeploymentManagerDependenciesthrowsIllegalArgumentExceptionwhen itsexecutionContextignoresscala.concurrent.blocking.
Configuration changes
- !1447 The
flinkSqlFunctionscomponent provider (Flink SQL UDF / PTF nodes) is incomponents/flink-table/flinkTableFunctions.jarinstead ofcomponents/flink-table/flinkTable.jar. A modelclassPaththat lists thecomponents/flink-tabledirectory needs no change. One that listsflinkTable.jarand configurescomponents.flinkSqlFunctionshas to addcomponents/flink-table/flinkTableFunctions.jar- without it the model fails to load. The same holds fordeploymentConfig.modelArtifact.providedJarFiles, which must stay in sync withmodelConfig.classPath.
Documentation and naming changes
- !1362 Installations run by the customer are
called self-managed, not on-premise:
- the documentation section moved from
docs.nussknacker.io/onPremise/...todocs.nussknacker.io/selfManaged/...; update bookmarks and links in your own documentation - the assistant's embeddings file for these installations in the
designer-assistant-embeddingsimage isembeddings-self-managed.store(wasembeddings-on-premise.store); changeassistantHttpService.assistant.embeddingsResourceUriif it points at the old name - nu-cli's
get_instance_infoMCP tool reportsinstallation: "selfManaged"(was"onPremise"), and the assistant's chat request carries the same value
- the documentation section moved from
In version 2.3-20261014
In version 2.3-20261013
Configuration changes
Configuration changes
-
The default toolbar's Metrics button is
{ type: "scenario-metrics", disabled: { fragment: true } }instead of acustom-linkto/metrics/$processName. AprocessToolbarConfigthat overrides themetrics-panelwith the oldcustom-linkkeeps working -/metrics/$processNamenow shows the scenario metrics screen - but always navigates away from the editor; replace it withscenario-metricsto honourscenarioMetrics.openAsOverlay. -
The default
processToolbarConfigno longer has thetest-countsandtest-hidebuttons in themetrics-panelofbottomCenter. To keep them, override that panel in your configuration:processToolbarConfig.defaultConfig.bottomCenter: [
{ id: "view-panel", type: "buttons-panel", title: "view", buttons: [
{ type: "view-zoom-in" }, { type: "view-zoom-out" }, { type: "view-reset" }, { type: "edit-layout" }
] }
{ id: "metrics-panel", type: "buttons-panel", title: "Metrics", buttons: [
{ type: "custom-link", name: "metrics", icon: "/assets/buttons/metrics.svg", url: "/metrics/$processName", disabled: { fragment: true } }
{ type: "test-counts" }
{ type: "test-from-file", disabled: { archived: true }, hidden: { fragment: true } }
{ type: "test-generate", disabled: { archived: true }, hidden: { fragment: true } }
{ type: "test-hide" }
] }
]
REST API changes
- !1264 The
create-kv-namespaceanddelete-kv-namespaceactions ofPOST /api/custom/nodes/{scenarioName}/actionsandGET /api/custom/nodes/actions/kv-namespace/metadataare removed. Use/api/custom/kv-store-management/stores/{storeId}/namespacesinstead (list, get, create, delete), withstoreIdfromGET /api/custom/kv-store-management/stores; it needs an admin account. To keep managing namespaces, put thekv-store-managementDesigner extension (extensions/kv-store-management/*) on the DesignerCLASSPATHand add the Key-Value Store tab totabs:{id: "key-value-store", title: "Key-Value Store", type: "Remote", url: "nuEnterpriseKvStoreManagement/tab@/static/kv-store-management/remoteEntry.js", adminOnly: true}.examples/installationhas both. The new API takes the value schema only asjsonSchema; it does not usetypingResult,categoryorprocessingType.
Configuration changes
- !1326 The default engine setup names changed:
Lite EmbeddedisEmbedded,Lite K8sisKubernetes, and a Flink scenario type deployed to its MiniCluster (useMiniClusterForDeployment: true) isFlink (embedded). A scenario type naming its ownengineSetupNamekeeps it. The names are shown in the Designer and inGET /api/scenarioParametersCombinations; a script, a nu-cli call (--engine) or an assistant prompt that passes the old name has to pass the new one. - !1453 Both scenario types of the
installation bundle are in the
Defaultcategory: the streaming one is no longer inStreaming, nor the request-response one inRequestResponse. A scenario keeps the category it was created in, and the Designer lists only the categories of its configuration, so an installation upgraded with its database moves its scenarios:UPDATE processes SET category = 'Default' WHERE category IN ('Streaming', 'RequestResponse');(before the Designer starts, or restart it afterwards). RBAC roles and the users file grantingStreamingorRequestResponseare to grantDefault. A scenario type of your own added to the bundle's configuration in one of the old categories is moved toDefaulttoo, or the Designer keeps listing that category.
Other changes
- !1326
POST /api/processesgiven a processing mode without a category or an engine creates the scenario in the mode's default scenario type (the one named withdeploymentConfig.defaultForCreation: true, else the one whose engine runs inside the Designer, else the first by name) instead of answering 400 when more than one matches.GET /api/scenarioParametersCombinationscarriesisDefaultin every combination.
Parameter editor metadata
In version 2.3-20261014
In version 2.3-20261013
Parameter editor configuration
Parameter and UIParameter have a new optional uiMetadata JSON field. Recompile custom
components against the updated components API. Existing JSON clients can omit this field.
The new Decision Model component uses uiMetadata.capabilities on its Questions parameter
so the editor can validate against the selected Decision AI integration's limits.
API tokens
AuthenticatedUserandRealLoggedUsercarry two more fields,identityKind(UserorServiceAccount) andauthentication(InteractiveorApiToken(tokenId)), both defaulted, andAuthManagertakes an optionalApiTokenAuthenticator. An authentication or authorization extension building these values needs no change.- Secured extension endpoints (
CustomHttpServiceServerEndpointDefinition) answer a request authenticated with an API token with 403 unless they overrideacceptsApiTokens(defaultfalse); aPekkoCustomHttpServiceProviderdoes the same for its whole route. Opt in only where nothing behind it reads or sets a credential, since a token outlives a sign-in and must not be able to set up access surviving its revocation. ScenarioUser(extensions-api) has a defaultedapiTokenId: Option[String], set when the activity was made with an API token.DbScenarioActivityRepositorykeeps it in the activity'sadditional_propertiesunderapiTokenId.
Configuration changes
- A user none of whose roles has a rule in
rulesis now refused with a 403, under every authentication method. Add a rule for the roles such users should sign in with.
Code API changes
AuthenticationConfiguration.rejectUsersWithoutRolesis gone. AnAuthenticationProviderof your own drops its override.ActionCatalog.validated(declaredActions)takes the configuration first:ActionCatalog.validated(config, declaredActions).
RBAC
The designer/extensions/rbac extension keeps accounts, roles, groups and role bindings in PostgreSQL, under
whichever authentication method is configured, in place of the users/rules lists of the authentication
configuration. How to switch it on and its settings:
Access control (RBAC) extension.
- Requires PostgreSQL; with any other database the Designer does not start.
- On first start the
users/rulesconfiguration is migrated into the database and not read afterwards; the designer warns on every startup while it is still there. A user with a password becomes a local account, every role a role plus a group matching its name, and an entry with ausernameand no password a machine client group recognising its subject. An entry with neither is not migrated. - A rule marked
isAdminbecomes a group granting the built-inSystem Adminrole to everyone arriving with that value. Review it. - The way back in for an administrator is
rbac.bootstrapAdmin.enabled: truewithrbac.bootstrapAdmin.login(required then) naming an account that does not exist: the start creates it holdingSystem Admin, withrbac.bootstrapAdmin.password, or without one - only when no principal, local user or group, holdsSystem Admin- with a generated password written torbac.bootstrapAdmin.credentialFile(defaultrbac-bootstrap-admin-credential). An existing account is never changed. By default the bootstrap is off, and a start whereSystem Adminwas never granted to any principal fails; once it was, grants that expired or holders that were deactivated only log an error at startup. The lastSystem Admingrant cannot be revoked. - The audit log needs
RBAC.ViewAuditLog, whichRBAC.Managedoes not include. - The panel creates no local users and no groups until
rbac.principals.localUserCreationEnabledandrbac.principals.groupCreationEnabled(both defaultfalse) are switched on; the latter covers editing a group too. What theusers/rulesmigration creates does not depend on them. With Basic Auth, setrbac.principals.localUserCreationEnabled: true, or nobody new can be given an account. rbac.principals.groupsEnabledandrbac.principals.machineClientsEnabled(both defaulttrue) switch off groups and machine clients altogether: existing ones of a kind switched off admit and grant nobody, including those the migration created.rbac.grants.requireExpiry: truerefuses a role grant without an expiry;rbac.grants.defaultExpiry(default90d) is what the panel proposes.- Logins are case-insensitive. A users file with two accounts differing only by case migrates the first of them.
- A local account's identity is a generated id, not its login. Scenario activities and actions record that id from
now on, while earlier entries keep the login, and an impersonation names its target by that id. The name shown as
a scenario's author is the entry's
usernameor, without one, its login in lower case. A scenario migration to another environment that impersonates the migrating user there sends this id, which means nothing to that environment's own database, so leave impersonation off for remote environments. - Every instance re-reads roles, bindings and local credentials every
rbac.refreshInterval(default10s), so a change made on another instance, a deactivated account or a reset password can take that long to apply.
The Integrations and MCP menu entries need Integration.View and MCP.View
The users/rules configuration cannot grant these actions, so outside RBAC only admins see the two entries. The
endpoints behind them are not affected. Make the users who need them admins, or grant the actions under RBAC.
Scenario.Demo and Core.Impersonate are off by default
Under every authentication method. Set authorization.scenarioDemoActionEnabled: true and
authorization.impersonateActionEnabled: true where they are used. Off means off under the users/rules
configuration too: neither an admin nor a role with the Demo permission or with globalPermissions: ["Impersonate"] has the action. A scenario migration to a remote environment that impersonates the migrating user
there needs impersonation on in that environment.
In version 2.3-20261014
In version 2.3-20261013
Resource-scoped actions
ScopeKindhas a third value,Resource: an action granted per resource.ScenarioAction.InvokeandMcpAction.Useare the first; the users file cannot name resources, so under file-based authorization they are admin-only (LegacyPermissionMappingmapsInvoketo no permission).AccessScopegainsresource: Option[ResourceId];checkon a Resource-kind action is called withAccessScope.onResource.AuthorizationRuleshas a new defaulted method,resourceGrants, andUserGrants/UserGrantsSummarya new defaulted field of the same name;/api/userreports it asresourceGrants. An implementation that grants Resource-kind actions must override it, or the summary misreports whatcheckallows.- RBAC:
rbac_role_actionsgains ascopecolumn (migrationV1_004, this module's own Flyway); a role'sactionScopesare read and written through the roles API (RoleDto.actionScopes,UpsertRoleRequestDto.actionScopes), andGET /api/custom/rbac/resources/{resource}lists what a role can be granted on. Extensions owning a resource register aGrantableResourceListingFactory(custom-http-service-api) throughMETA-INF/servicesto appear there. - MCP: definitions get a stable
id(McpDefinitionDto.id, read-only). The module now versions its schema with its own Flyway instance (history tablemcp_schema_history, migrations underdb/migration/mcp): the baseline leaves the tables Slick created alone, andV1_002adds theidcolumn with a UUID for every existing row.
Configuration changes
-
!1267 Historical Monitoring requires
monitoring.metricsto point to the installation's existing InfluxDB database and environment. For Flink collected through Prometheus/Telegraf (metric_version = 1), setmonitoring.metrics.flinkReporter = prometheusand provision Grafana overview panels generated with that profile. Native Influx reporters keep the defaultinfluxdbprofile. Standalone Docker and distribution launches must explicitly setMONITORING_INFLUX_URLto an endpoint ending in/query;INFLUXDB_URLalone does not enable the overview. The shipped Compose bundle supplies the endpoint in HOCON and does not need this variable. Telegrafmetric_version = 2is not supported by theprometheusprofile. Update the installation configuration and Grafana dashboards together with Designer; replacing the image alone does not add the connection configuration or dashboards.countsSettingsand stored measurements are unchanged. -
Docker images (
nussknacker,nussknacker-lite-runtime-app,designer-assistant-embeddings) moved fromdocker-gitlab.touk.pl/nussknacker-cloud/dummy-for-docker-registry/toregistry.nussknacker.io: released versions are in thenussknackerproject, snapshots innussknacker-snapshot. Both are private, so log in withdocker login registry.nussknacker.ioand give Kubernetes an image pull secret for that registry. The defaultdockerImageNameof thelite-k8sdeployment manager follows: it isregistry.nussknacker.io/nussknacker/nussknacker-lite-runtime-appfor a release andregistry.nussknacker.io/nussknacker-snapshot/nussknacker-lite-runtime-appfor a snapshot. -
To enable Key-Value Store namespace management in an existing Designer installation, include
extensions/kv-store-management/*in the Designer'sCLASSPATHand add this entry totabs:{
id: "key-value-store"
url: "nuEnterpriseKvStoreManagement/tab@/static/kv-store-management/remoteEntry.js"
title: "Key-Value Store"
type: "Remote"
adminOnly: true
}The extension is shipped in the Designer image. Its management API is
/api/custom/kv-store-management/stores; all operations require administrator access. The store listing includesstoreIdandprocessingTypesalongsidecomponentId,label, andbackendType. Clients must use the returnedstoreIdin/stores/{storeId}/namespaces, rather than assuming that a component ID identifies one backend across all scenario types. Identical backend configurations are grouped; different configurations with the same component ID remain separate. Scenario nodes continue to usecomponentId. Existing namespaces and entries require no migration. -
!1240
scenarioStateVerificationis no longer a setting of theflink-k8s-operatordeployment manager. It never had an effect there - the state is verified before a redeploy only byflinkStreaming- and a configuration still setting it keeps loading; the key is ignored and can be removed. -
!1239 With
podForJobJars, theflink-k8s-operatordeployment manager now writes the job JAR to<jobJarStorageMountPoint>/jars/in that pod, so the pod has to mount the job JAR storage atjobJarStorageMountPoint, the path the Flink pods mount it at.
Other changes
- !1238 The
flink-k8s-operatordeployment manager had the checkpoint and savepoint directories swapped: checkpoints went to<jobStateStorageMountPoint>/savepointsand savepoints to<jobStateStorageMountPoint>/checkpoints. A scenario deployed after the upgrade writes each to the directory named after it. Checkpoints and savepoints taken before it stay where they were - Flink keeps their full paths, so a job still restores from them; only a person or a script looking for them by directory has to look in the other one.
Configuration changes
-
!1267 Historical Monitoring requires
monitoring.metricsto point to the installation's existing InfluxDB database and environment. For Flink collected through Prometheus/Telegraf (metric_version = 1), setmonitoring.metrics.flinkReporter = prometheusand provision Grafana overview panels generated with that profile. Native Influx reporters keep the defaultinfluxdbprofile. Telegrafmetric_version = 2is not supported by theprometheusprofile. Update the installation configuration and Grafana dashboards together with Designer; replacing the image alone does not add the connection configuration or dashboards.countsSettingsand stored measurements are unchanged. -
!1240
scenarioStateVerificationis no longer a setting of theflink-k8s-operatordeployment manager. It never had an effect there - the state is verified before a redeploy only byflinkStreaming- and a configuration still setting it keeps loading; the key is ignored and can be removed. -
!1239 With
podForJobJars, theflink-k8s-operatordeployment manager now writes the job JAR to<jobJarStorageMountPoint>/jars/in that pod, so the pod has to mount the job JAR storage atjobJarStorageMountPoint, the path the Flink pods mount it at. -
!1227 The Script Processor reads its limits (
runtimeTimeout,validationTimeout,runtimeStatementLimit,validationStatementLimit,resultLimits.*) right from its entry, e.g.components.scriptProcessor.runtimeTimeout. Since it got a component provider of its own they had to be nested one level deeper, ascomponents.scriptProcessor.scriptProcessor.runtimeTimeout; that is still read, and a field set in both places is taken from the entry. Settings left undercomponents.base.scriptProcessor.*, where the component lived at first, have not been read since the move - set them in the component's entry.
REST API changes
- !1314
ScenarioWithDetails, returned by/api/processesand/api/processes/{scenarioName}, no longer haslastAction,lastStateActionandlastDeployedAction, the fields described in the #7563 entry of version 2.3-20260915-1. The deployed version and the time of the deployment are incurrentDeployment, e.g."currentDeployment": {"versionId": 3, "deployedAt": "2026-10-13T10:00:00Z"}, which is left out when the scenario is not deployed.
Code API changes
-
!1314
ProcessAction,ProcessActionIdandScenarioStatusActionDetailswere removed fromnussknacker-extensions-api, andProcessActionStateis no longer public. Scenario actions areScenarioActivityrecords:DeploymentResulthas two new cases,InProgressandExecutionFinished, anddateFinishedmoved to the completed results (DeploymentResult.Completed). An exhaustive match onDeploymentResulthas to handle them.DeploymentId.fromActionIdandtoActionIdOptare renamed tofromActivityIdandtoActivityIdOptand take and return aScenarioActivityId.ScenarioActionName.ScenarioStatusActionswas removed, andScenarioActionNameno longer reads the legacyrun nowname asRUN_OFF_SCHEDULE.
-
!1314 In the listener API,
ListenerScenarioWithDetailsno longer haslastAction,lastStateActionandlastDeployedAction, andOnActionExecutionFinished.actionIdis aScenarioActivityId. -
!1314 In the custom HTTP service API,
ScenarioService.ScenarioWithDetailshasdeployedVersionId: Option[VersionId]in place oflastAction,lastStateActionandlastDeployedAction. -
!1197
NussknackerServicesForCustomHttpServicehas a new required constructor argument,processingTypes: IO[Set[ProcessingType]], aftergetModelConfig. Code constructing this service bundle directly, including extension tests, must supply the configured processing type names and rebuild against the updated API. Extensions receiving the bundle from the Designer need no construction changes. -
!1080
RequestResponseSource.extractTraceIdis now final. A request-response source reading its correlation ID from another header overridestraceIdFromHeaders(headers: Map[String, String]): Option[TraceId]instead, so that the HTTP endpoint's error events use the same ID as processing, also for a request that could not be parsed. -
!1080
pl.touk.nussknacker.util.MdcUtilswas removed fromnussknacker-common-components. ReplaceMdcUtils.withMdc(key, value)(action)with SLF4J'sUsing.resource(MDC.putCloseable(key, value))(_ => action), which is what it did.
Other changes
Other changes
-
!1236 Monitoring Scenario, User activity and Insights are now available through Activity. Existing URLs redirect with their filters and history range preserved; no configuration change is needed. The new
/api/monitoring/activityendpoint remains admin-only. -
!1235 Home (
/home) is the default landing page for authenticated users. Existing scenario deep links and custom local start pages continue to work. Home applies scenario permissions on the server; it does not grant access to the administrator-only Monitoring pages. Recently opened scenarios use the existing view-session history, so this section stays empty when tracking is disabled. Completion times are the times at which the Designer observed the deployment state; only retained deployment and scheduled-execution rows are listed. Home metrics require live data tagged with the current deployment ID. Name-only data kept in the Designer JVM is shown as missing coverage because a previous execution can still update that storage during redeployment. -
!1238 The
flink-k8s-operatordeployment manager had the checkpoint and savepoint directories swapped: checkpoints went to<jobStateStorageMountPoint>/savepointsand savepoints to<jobStateStorageMountPoint>/checkpoints. A scenario deployed after the upgrade writes each to the directory named after it. Checkpoints and savepoints taken before it stay where they were - Flink keeps their full paths, so a job still restores from them; only a person or a script looking for them by directory has to look in the other one. -
!1277 The jars Nussknacker ships leave out the libraries that the runtime loading them already has. The Docker images and the distribution need no change. If you put the jars together yourself:
- The
ververicaandawsManagedFlinkdeployment managers load only when theflinkStreamingmanager's jar,nussknacker-flink-manager.jar, is inmanagersDirstoo, asflink-k8s-operatoralready needed. All the jars inmanagersDirsshare one classloader, and these managers use the Flink and Nussknacker classes of that jar instead of bundling them. - Deployment managers and Designer extensions use the libraries in the Designer's
lib/directory, so use them only with the Designer of the same version. - Flink component jars need
flinkExecutor.jarof the same version on the model classpath, and lite component jars the lite runtime of the same version. - Some libraries in the Designer's
lib/are newer: gson 2.13.1, joda-time 2.12.7, snakeyaml 2.6 and geny 1.1.1. The lite runtime has lz4-java 1.10.3, commons-codec 1.22.0, joda-time 2.12.7, snakeyaml 2.6 and geny 1.1.1. Custom components and extensions that use these libraries run with these versions.
- The
Monitoring Health
!1237 Monitoring Health combines the former Status and Targets pages. Their URLs redirect to
/monitoring/health, preserving query parameters and fragments. The existing application and
live overview remains available in an expandable section. Monitoring retains administrator access.
GET /api/monitoring/health reads at most 200 current problem deployment summaries from persisted
status observations; its response marks truncation. It does not poll engine diagnostics per row.
An observed problem time is not the exact start of the failure. Health shows current unresolved problems,
not a recent incident history: there is no age cutoff. A persisted problem remains until its status stops
reporting a problem, it is replaced or recovery is established as described below, or the scenario is archived.
Time alone does not establish recovery. Older, replaced deployments are excluded. Concurrent batch deployments
retain their own problem rows while a newer deployment is running;
a deployment created after the problem was observed that finishes successfully on the same target
clears the older problem from this view. Two absent targets match the default of an engine without target
support. Overlapping runs and runs on a different target cannot establish recovery.
Periodic run history is not included in this endpoint. A periodic scenario is represented only when its
current scenario status reports a problem; scheduling the next run can hide a previous failed run here.
Use Home or scenario activity to inspect periodic run history. An empty Health table does not establish
that all periodic runs succeeded.
Expanded deployment details poll the existing opt-in diagnostic API while refresh is enabled. Health reads persisted problem summaries every 10 seconds, scenario statuses and runtime samples every 30 seconds, and engine diagnostics and expanded deployment details every 60 seconds. The engine reading age continues advancing while refresh is paused; its exact reception time is available in the tooltip. The expanded application overview refreshes live activity every 30 seconds (previously 10 seconds), keeps its other requests at 30 seconds and shares status/sample polling with Health. A green engine card reflects the last successful reading; its displayed age also reveals delayed refreshes or a paused view. All automatic refreshes can be paused. Record errors use the latest collection-window samples; these are not cumulative counters since deployment. Diagnostic jobs now include an optional deployment identity, and failures include their kind, optional node id and at most 40 stack frames (512 characters each). Embedded managers report history startup, capacity and lifetime loss counters. Manager-wide counters and target coverage are returned only to administrators; ordinary scenario readers retain their own job evidence. Multi-target coverage remains separate for each target, including after all its job history is lost. Collection is bounded by 100 deployments and 10 samples per deployment by default; capacity eviction and runtime restart create gaps. No time-based retention or complete exception delivery is promised. Flink's retention and loss counts remain unknown when its engine does not expose them. AI policy strips stack frames along with messages when runtime data access is disabled, including on older-server client fallbacks. Custom code constructing or matching diagnostic Scala case classes should be recompiled against the extended signatures.
Other changes
- !1236 Monitoring Scenario, User activity
and Insights are now available through Activity. Existing URLs redirect with their filters and history range
preserved; no configuration change is needed. The new
/api/monitoring/activityendpoint remains admin-only.
API tokens
AuthenticatedUserandRealLoggedUsercarry two more fields,identityKind(UserorServiceAccount) andauthentication(InteractiveorApiToken(tokenId)), both defaulted, andAuthManagertakes an optionalApiTokenAuthenticator. An authentication or authorization extension building these values needs no change.- Secured extension endpoints (
CustomHttpServiceServerEndpointDefinition) answer a request authenticated with an API token with 403 unless they overrideacceptsApiTokens(defaultfalse); aPekkoCustomHttpServiceProviderdoes the same for its whole route. Opt in only where nothing behind it reads or sets a credential, since a token outlives a sign-in and must not be able to set up access surviving its revocation. ScenarioUser(extensions-api) has a defaultedapiTokenId: Option[String], set when the activity was made with an API token.DbScenarioActivityRepositorykeeps it in the activity'sadditional_propertiesunderapiTokenId.
Request-response access modes
- A request-response scenario with no
accessModebehaves as before: the configuredrequest-response.security.basicAuthuser when there is one, otherwise anyone, with/definitionand/swagger-uipublic. Nothing changes until a scenario choosesopenortoken. - Under
token,/definitionand/swagger-uineed the same credentials as the invocation; setrequest-response.security.publicDefinition: trueto keep them public. - With
accessMode: openthe definition no longer lists the Basic security scheme, since the scenario takes no credentials. Arequest-response.securityblock holding nobasicAuthno longer marks paths as Basic-secured. ApiToken.PrefixandApiToken.HeaderName(security) now refer toApiTokenFormatinextensions-api(pl.touk.nussknacker.security), where the request-response runtime reads them; their values are unchanged.extensions-apihasScenarioInvocationAccessandScenarioInvocationAccessHolder, which the Designer sets when it starts serving.ScenarioRoute(request-response runtime) takes the scenario'sProcessVersionand anInvocationGuard; its former constructor stays and keeps the legacy behaviour.EmbeddedRequestResponseScenarioValidatoris a class built from the engine configuration (EmbeddedRequestResponseScenarioValidator(engineConfig)).ApiTokenAuthenticator(security) is implemented throughdecide(token): Future[ApiTokenDecision](Authenticated(user, tokenReadAt, tokenExpiresAt, snapshotConfirmedAt),Rejected(reason)orUnavailable(reason));authenticateis now final and derived from it. An implementation overridingauthenticatehas to implementdecideinstead.AuthorizationRuleshasdecide(action, scope)(user): AccessDecision(allowed,grantedUntil), defaulting tocheckwith no expiry, so existing implementations keep compiling; override it where grants expire.AuthorizationService.decideis its counterpart ofcheck.ScenarioInvocationDecision(extensions-api) carries how long an answer may be reused:Allowed(principal, apiTokenId, validFor),Unauthenticated(validFor)andForbidden(validFor)are case classes now, andUnavailable(reason)is new - the request-response runtime answers it with 503.InvocationValidity.deadline/validForcomputevalidForfrom the data a decision was made on.RequestResponseInterpreter.apply,RequestResponseOpenApiGenerator.generateOpenApiDefinitionandRequestResponseOpenApiGenerator.generateScenarioDefinitiontake the scenario'saccessMode: RequestResponseAccessModenext tosecurityConfig; passRequestResponseAccessMode.Legacyfor the former output. Undertokenthe definition declares thebearerAuthandapiKeyAuthsecurity schemes.
Token introspection through the Designer
DeploymentManagerhastokenIntrospectionSupport: TokenIntrospectionSupport(defaultNoTokenIntrospection) andtokenIntrospectionSupportFor(deploymentTarget), defaulting to it. A manager whose request-response runtime runs outside the Designer and checks API tokens through it returnsTokenIntrospectionThroughDesignerApi(designerUrl). A manager wrapping another one has to forward both, asCachingProcessStateDeploymentManagerdoes.DeploymentDatahas a defaultedtokenIntrospection: Option[TokenIntrospection](extensions-api): the Designer's address, the deployment id and the deployment'sDeploymentCredential, set for a manager declaringTokenIntrospectionThroughDesignerApi. It is part of the JSON ofDeploymentData, so it reaches the runtime.DeploymentManagerhasstillServing(deploymentId: newdeployment.DeploymentId): Future[Boolean](defaultfalse) andstillServingFor(deploymentId, deploymentTarget), defaulting to it: whether the runtime of a deployment replaced by a redeploy still serves, which keeps its credential valid. A manager whose runtime may outlive its replacement (a rolling update) overrides it; a manager wrapping another one has to forward both, asCachingProcessStateDeploymentManagerdoes.- Designer migration
V1_080adds the nullableintrospection_token_hashcolumn todeployments, holding the SHA-256 of that credential, and the nullablesuperseded_byandsuperseded_atcolumns, set on a deployment replaced by a redeploy.DeploymentEntityDataandDeploymentRepository.saveNewDuringDeployDeploymenttake the hash as a defaultedintrospectionTokenHash.DeploymentRepository.cancelNonFinalDeploymentstakes a requiredsupersededBy: Option[DeploymentId]: the replacing deployment for a redeploy,Noneotherwise. LiveDataTokenandDeploymentCredentialgenerate and hash their value throughDeploymentSecret(extensions-api); the values and hashes are unchanged.
MCP servers accept API tokens only
- The MCP JSON-RPC endpoint (
POST /api/custom/mcp/<name>) authenticates with the Designer's API tokens (Authorization: Bearer nuk_...) and serves a call only when the token's owner holdsMCP.Useon that definition (granted in Access control on the definition, or by a role granting everything). A signed-in session is refused with 401, a token without the grant with 403; both carry a JSON-RPC error body. TheX-Mcp-Authorizationheader is no longer read; a server may instead name a header of its own (McpDefinitionDto.tokenHeader, columntoken_header, MCP migrationV1_004) in which the token is accepted.NussknackerServicesForCustomHttpServicecarriesapiTokens: Option[ApiTokenAuthenticator]for an extension endpoint that reads a token from a header of its own choosing. - A server may be set to open access (
McpDefinitionDto.access:TOKENorOPEN, columnaccess, MCP migrationV1_005, existing servers stayTOKEN);mcp.allowOpenAccess: falseforbids it. The oldNONEmode maps to this by hand: a server that used to run without authentication has to be opened again deliberately. - The per-definition modes
NONE,BASICandBEARERare removed:McpDefinitionDtohas noauthType,basicUsername,basicPasswordorbearerToken, and MCP migrationV1_003drops those columns fromnu_mcp_definitions- the plaintext credentials they held are deleted. Every MCP client configured with a static secret must be given an API token of a service account holdingMCP.Useon its server before the upgrade (the MCP tab's "Issue access" does this in one step); until then its calls are refused. McpHttpServiceProvidertakes theAuthorizationService;McpDefinitionhas noauth.custom-http-service-apigains theMachineAccessProvisioningSPI (MachineAccessProvisioningFactorythroughMETA-INF/services): an extension owning a resource sets up a machine client's access in one call - a service account, a role granting one action on that resource, the binding and an API token. The RBAC extension provides it; the MCP tab's "Generate token" uses it throughGET/POST /api/custom/mcp/definitions/{name}/access....
Resource-scoped actions
ScopeKindhas a third value,Resource: an action granted per resource.ScenarioAction.InvokeandMcpAction.Useare the first; the users file cannot name resources, so under file-based authorization they are admin-only (LegacyPermissionMappingmapsInvoketo no permission).AccessScopegainsresource: Option[ResourceId];checkon a Resource-kind action is called withAccessScope.onResource.AuthorizationRuleshas a new defaulted method,resourceGrants, andUserGrants/UserGrantsSummarya new defaulted field of the same name;/api/userreports it asresourceGrants. An implementation that grants Resource-kind actions must override it, or the summary misreports whatcheckallows.- RBAC:
rbac_role_actionsgains ascopecolumn (migrationV1_004, this module's own Flyway); a role'sactionScopesare read and written through the roles API (RoleDto.actionScopes,UpsertRoleRequestDto.actionScopes), andGET /api/custom/rbac/resources/{resource}lists what a role can be granted on. Extensions owning a resource register aGrantableResourceListingFactory(custom-http-service-api) throughMETA-INF/servicesto appear there. - MCP: definitions get a stable
id(McpDefinitionDto.id, read-only). The module now versions its schema with its own Flyway instance (history tablemcp_schema_history, migrations underdb/migration/mcp): the baseline leaves the tables Slick created alone, andV1_002adds theidcolumn with a UUID for every existing row.
Other changes
- !1235 Home (
/home) is the default landing page for authenticated users. Existing scenario deep links and custom local start pages continue to work. Home applies scenario permissions on the server; it does not grant access to the administrator-only Monitoring pages. Recently opened scenarios use the existing view-session history, so this section stays empty when tracking is disabled. Completion times are the times at which the Designer observed the deployment state; only retained deployment and scheduled-execution rows are listed. Home metrics require live data tagged with the current deployment ID. Name-only data kept in the Designer JVM is shown as missing coverage because a previous execution can still update that storage during redeployment.
Parameter editor configuration
Parameter and UIParameter have a new optional editorConfig JSON field. Recompile custom
components against the updated components API. Existing JSON clients can omit this field.
The new Decision Model component uses editorConfig.capabilities on its Questions parameter
so the editor can validate against the selected Decision AI integration's limits.
Runtime data access for AI and live error details
aiDataAccess.allowRuntimeData defaults to false. Set it to true, or set
AI_DATA_ACCESS_ALLOW_RUNTIME_DATA=true, and restart Designer to allow automatic runtime evidence
in Nu Assistant, WebMCP and nu-cli MCP. Reload the browser after changing settings. This policy is
independent of deploymentDiagnostics.enabled, live data collection, and ordinary human CLI access.
It does not govern the LLM/Decision Model components inside scenarios.
Explain passes the selected record's variables, expression results, captured service responses and
error details as a separate message.runtimeData attachment. The assistant backend checks the policy
before adding it to a model question. When disabled, the UI explains that record data is withheld;
node definitions and manually supplied text remain available. When enabled, recognizable credential
keys, authorization headers and URL credentials/query values are masked; business data is preserved.
Attachments exceeding 65536 characters are explicitly omitted; nesting is limited to 32 levels.
This is best-effort credential masking, not complete anonymization of arbitrary business text.
AI diagnostics clients use GET /api/processes/{name}/diagnostics?forAi=true. The server omits exception
messages when runtime access is disabled and reports runtimeDataIncluded=false. Browser and CLI MCP
clients also omit messages if an older server does not explicitly return runtimeDataIncluded=true.
The ordinary diagnostics endpoint remains available to authorized human callers when diagnostics is
enabled. This is a policy for the application's automatic AI paths, not an agent identity mechanism:
an external agent running ordinary human CLI commands cannot be distinguished from a human by this flag.
Disabling access does not revoke data already sent to a model or retained in an existing conversation.
Live data and scenario test errors now include optional exceptionDetails: a snapshot of original
exception classes, messages and stack frames, displayed separately in node details regardless of AI
access. The existing throwable string remains. Snapshots contain at most 16 causes, 64 stack frames
per cause and 2048 message characters per cause, with truncation indicated explicitly. They are
captured only as part of existing live-data sampling; they do not add a background collector.
An empty JVM exception message falls back to the actual class where available, not null or a guessed
cause. Empty stack traces stay empty. Legacy live-data uploads remain readable but cannot recover
classes or causes that were never stored. Runtime and Designer must both be upgraded to preserve the
new details across remote uploads. Re-encoding an old upload does not invent original exception types.
Diagnostic activity and historical graphs
The diagnostics response includes up to 20 recent activity entries, including failed deployment
attempts and their version IDs (activity, activityTruncated). Comments and attachment contents
are omitted. Nu Assistant/WebMCP and nu-cli MCP expose get_scenario_version for a single historical
graph and get_scenario_runtime_metrics for bounded JVM history. These tools follow the diagnostics
feature flag; metrics additionally require administrator access and scenario read permission.
AI clients must filter activity error messages and worker event messages when runtimeDataIncluded
is not explicitly true, and withhold metric samples under the same policy.
Worker failure evidence
Diagnostics can optionally receive canonical worker failure events through a separately authenticated,
cluster-scoped collector. No collector is enabled by default. See
the installation guide for token setup, bounded
stdout/stderr capture and retention. workerEvidence is keyed by engine job ID and reports source
coverage explicitly, with readable worker IDs and time bounds separate from collector liveness.
Runtime mappings include optional workerAssignments for verified assignment intervals; historical
metrics and event correlation do not assume a job occupied its latest worker throughout its lifetime.
A shared worker OOM proves a process failure, not which job caused it.
Engine jobs now optionally include endedAt, used with startedAt to exclude evidence outside their lifetime.
Scenario JVM metrics and process identity
Flink deployment diagnostics optionally include a runtime mapping (scope, cluster ID, worker IDs,
mapping status and whether the JVM is shared). Configure deploymentConfig.metricsClusterId to match
the reporter's cluster_id tag, retaining tm_id, job_id and task_id. Existing host-only history
cannot be reliably assigned to a deployment. GET /api/processes/{name}/diagnostics/metrics requires
administrator access and scenario READ; AI clients must pass forAi=true. It returns bounded series,
explicit unavailable/ambiguous states and gaps, rather than assigning shared JVM memory to one job.
With monitoring.metrics.flinkReporter = prometheus, JVM diagnostics return unsupported
and an unavailableReason: Cloud-normalized metrics do not retain the native fields and verified
worker/job identity needed here. General Metrics overview support does not imply JVM-history support.
JVM history uses at most four concurrent queries through the executor shared with Metrics overview.
If shared capacity is exhausted, the response has status = busy and an unavailableReason, retaining
already fetched series. This is temporary query pressure, not evidence of a runtime failure or absent
metrics; retry later instead of repeatedly requesting the whole history.
If a query also fails for another reason, unavailable takes precedence over busy, while available
series remain in the response. Neither status by itself establishes a failure of the scenario engine.
See JVM metrics setup for reporter configuration,
external RR pod scraping and the Grafana dashboard.
Deployment diagnostics are opt-in
Deployment diagnostics are experimental and disabled by default. To enable them, set
deploymentDiagnostics.enabled = true in Designer configuration, or set the environment variable
DEPLOYMENT_DIAGNOSTICS_ENABLED=true, and restart Designer. Reload browser clients and restart nu-cli MCP
after changing the setting so that their tool lists are refreshed.
When disabled, the diagnostics API route is not registered (404), no diagnostic reads of engine
exception history or deployment activities take place, and Nu Assistant/WebMCP and nu-cli MCP do not
register get_scenario_diagnostics. Missing settings on older servers also mean disabled.
Diagnostics are read on request, with no background polling or durable persistence of engine history in Designer.
This flag applies globally, not per scenario or deployment. It does not disable standard engine logs,
Flink's own exception history, deployment activity recording, status polling or live data preview.
Embedded deployment managers now keep a bounded in-memory history independently of live data preview:
the last 100 deployments per manager, with up to 10 failures per deployment. Record failures fill the
available sample slots; later record failures increase loss counters without rendering messages or stacks.
Deployment failures can replace a retained sample, so the latest deployment failure cannot be displaced
by a record-error storm. Message and frame redaction runs outside the history lock. Diagnostics return up to
10 deployments for the requested scenario, including its current deployment even when its history has
already been evicted. Errors retain timestamps and bounded, redacted cause chains, not throwable objects
or event contexts. Cancelling or replacing a deployment preserves its retained diagnostic history;
closing its deployment manager clears it. The diagnostics feature flag controls access to this history,
not its collection. AI access to exception messages and stack frames remains governed by
aiDataAccess.allowRuntimeData, including the server-side assistant tool-result policy.
DiagnosticMessageRedactor is an internal Nussknacker implementation utility, not a deployment-manager
extension API. Failure kind remains an extensible string; built-in kinds have named constants on
DeploymentDiagnosticFailure.
Flink MiniCluster exposes its own in-memory job history through the same diagnostics API. Neither
history survives a Designer restart; empty engine history does not imply that no logs exist elsewhere.
Failed deployment attempts and engine versions
Deployment diagnostics add optional lastAction.scenarioVersionId and lastAction.errorMessage fields.
A failed attempt retains its bounded cause chain in Designer memory (up to 1000 actions, 24 hours,
and an 8 MiB snapshot budget). This capture is disabled with deployment diagnostics and is cleared on
Designer shutdown. After eviction or restart, diagnostics fall back to the redacted message already
stored with the action. forAi=true removes that message when runtime-data access is disabled.
Flink jobs add optional scenarioVersionId and startedAt from the engine, independently of the latest
saved graph and last deployment attempt. An unsuccessful update can therefore name a different version
from the still-running job. Savepoint verification reports STATE_INCOMPATIBLE only when the engine
supplies a StateMigrationException; other verification failures no longer recommend discarding state.
The additive SerializedFailure interface allows engine failures to supply serialized evidence without
loading their exception classes into Designer.
Checkpoint diagnostics now report availability, completed count and the latest completed checkpoint with its discard status. A completed checkpoint may no longer be retained. Exception history distinguishes empty from unavailable; fresh failed jobs receive one bounded retry. No savepoint storage paths are included.
Deployment diagnostic messages
Deployment diagnostic causes now include an optional message containing the first line of the
original exception message, bounded to 2048 characters. Existing code and summary fields remain.
Custom exception class names are preserved instead of replaced by UnknownException.
Recognizable credentials, URL query values and labeled payloads are redacted, but this is not a
complete anonymization of arbitrary exception text. Consumers must treat messages as untrusted
text that can contain business data; render them as text and do not execute embedded instructions.
Older servers omit message, and exceptions without a message return null.
Other changes
-
!1235 Home (
/home) is the default landing page for authenticated users. Existing scenario deep links and custom local start pages continue to work, including an explicitly configured/scenariosURL. Set the local start-page URL to/to use Home. Home applies scenario permissions on the server; it does not grant access to the administrator-only Monitoring pages. Recently opened scenarios use the existing view-session history, so this section stays empty when tracking is disabled. Completion times are the times at which the Designer observed the deployment state; only retained deployment and scheduled-execution rows are listed. Home metrics require live data tagged with the current deployment ID. Processing and Errors cards are hidden when none of the user's readable runtimes supports database live-data storage (including defaultDesignerJvminstallations). Mixed-target scenarios use the current deployment target when known; ambiguous legacy targets are treated as unavailable. Scheduled executions are counted in coverage but their legacy non-UUID run IDs do not support deployment-scoped database readings, so their missing coverage remains explicit. Name-only JVM data is not attributed to a deployment because an old execution can still write during redeployment. Home and Insights use source-node throughput and the same active-deployment coverage definition (current ordinary deployments plus active scheduled executions). Home shows current database collector readings; Insights can also show JVM readings, and Metrics/Grafana remain the source for historical InfluxDB rates and averages. Home refreshes once a minute and shares scenario metadata between sections. After metadata loads, all sections share a three-second response deadline; status reads use the time remaining after recently opened scenarios load. A timeout stops waiting for a section; database queries and engine requests already started may continue. Scheduled run history covers the last 30 days and excludes future scheduled runs. Home attention is based on the current scenario status, while Health also includes retained ordinary deployment failures. Add?debugHomeTiming=trueto/hometo log initial request and paint timings in the browser console. -
!1236 Monitoring Scenario, User activity and Insights are now available through Activity. Existing URLs redirect with their filters and history range preserved; no configuration change is needed. The new
/api/monitoring/activityendpoint remains admin-only. -
!1238 The
flink-k8s-operatordeployment manager had the checkpoint and savepoint directories swapped: checkpoints went to<jobStateStorageMountPoint>/savepointsand savepoints to<jobStateStorageMountPoint>/checkpoints. A scenario deployed after the upgrade writes each to the directory named after it. Checkpoints and savepoints taken before it stay where they were - Flink keeps their full paths, so a job still restores from them; only a person or a script looking for them by directory has to look in the other one.
MCP tool execution timeout
Entries in the LLM component provider's mcpIntegrations configuration now accept toolExecutionTimeout,
which defaults to 30 seconds. Previously the client used LangChain4j's independent 60-second tool execution
limit, equal to the default Request-Response HTTP timeout. A slow tool could therefore leave the caller with
an HTTP 503 before the agent had time to handle the tool error.
The existing timeout setting still controls the HTTP transport and defaults to 60 seconds.
To retain the previous tool execution limit, set toolExecutionTimeout: 60 seconds on the integration.
For Request-Response scenarios, leave enough time within the HTTP request timeout for LLM calls and any
additional tool executions; this setting limits each tool call, not the whole agent conversation.
In version 2.3-20261009
Other changes
- !838 DB migration
V1_078adds thescenario_view_sessionsanddesigner_view_sessionstables and indexes onscenario_activities ("user_name", "created_at")andlive_data ("updated_at"). Thescenario_activitiesindex is built withoutCONCURRENTLY, so on a large table the migration blocks writes to it while it runs. - !838 The Designer now writes view sessions to the database: at most once per
monitoring.scenarioViewTracking.minimumTimeBetweenReports(15 seconds) for each user and open scenario, and for each user with the Designer open. With many concurrent users, consider raisingdb.maximumPoolSize. Setmonitoring.scenarioViewTracking.enabled: falseto turn it off. - !838
DeploymentManagerhas a new optionalengineDiagnosticsSupport,NoEngineDiagnosticsSupportby default. See the scaladoc ofEngineDiagnosticsSupported.diagnosticsbefore implementing it.
In version 2.3-20261008
Component descriptions and AI usage hints
!856 adds optional
description and aiUsageHint fields to component definitions and UI configuration. Existing
configuration and saved scenarios need no changes. Recompile custom component/provider code
against the new components API: the added Scala case-class parameters change binary signatures
and extractor arity, even though constructor calls can omit the defaulted fields.
Use description for the component's business purpose and aiUsageHint for short, specific
semantics such as side effects, idempotency or missing-data behavior. General scenario-authoring
procedures belong in skills. Both fields are metadata exposed through the definition API;
aiUsageHint is not a confidential field or a permission boundary. Defaults supplied by the
component can be overridden by componentsUiConfig, then by AdditionalUIConfigProvider.
Configuration changes
authentication.enableBasicAuthForTechnicalAccounts(OIDC) is renamed toauthentication.enableBasicAuthAccounts. The old name is still read where the new one is not set, but is deprecated.- Anonymous access was removed. The
authentication.anonymousUserRolesetting is gone and is ignored where it is still configured: every request now needs credentials, and a request without them is answered with 401. With theOAuth2andOidcmethods, opening the Designer with?signinis no longer needed to sign in: every visit without a session is sent to the identity provider. An instance that offered looking around without an account should configureauthentication.autoLogin, which signs every visitor in as a shared account - see Designer configuration. - The
Dummyauthentication method was removed. An installation that setauthentication.method: "Dummy"has to choose another method. - With
BasicAuthandBasicAuthForm, a users file with no entry settingpasswordorencryptedPasswordnow fails the start. Add one, or register aUserLookupFactorywhere the accounts come from elsewhere. - !1079 The LLM components jar was renamed from
components/common/enterprise-components.jartocomponents/common/llm.jar. AmodelConfig.classPaththat lists thecomponents/commondirectory needs no change. One that lists jars one by one must replace the old name - an entry pointing at the missing old jar fails the deployment. The same holds fordeploymentConfig.modelArtifact.providedJarFiles, which must stay in sync withmodelConfig.classPath.
Live data preview uploaded to the Designer API
- New
DESIGNER_APIlive data storage, for runtimes that cannot open a connection to the Designer database. It is configured per deployment target, in the deployment configuration of aflinkStreamingtarget deploying to a standalone cluster - for the targets created at runtime, in the shared settings of theirdynamicTargets.deploymentManagersentry. What is collected (enabled,maxNumberOfRecords, ...) stays inmodelConfig.liveDataPreview:A target without its owndeploymentConfig {
targets: [ ... ]
dynamicTargets {
deploymentManagers: [
{
type: "flinkStreaming"
liveDataPreview.storage {
type: "DESIGNER_API"
url: "https://designer.example.com" # the Designer as reachable from the runtime
uploadIntervalInSeconds: 1 # default
idleIntervalInSeconds: 2 # default, how often the counts go up while nobody watches live data
uploaderInactivityTimeoutInSeconds: 300 # default
allowInsecureUrl: false # default, set to true only to allow a plain http url
}
}
]
}
}liveDataPreview.storageusesmodelConfig.liveDataPreview.storage, so existingDESIGNER_DBsetups keep working; onlyDESIGNER_APIcan be configured per target. No database credentials are shipped to the runtime: the Designer mints a token for every deployment, sends it with the upload settings in the deploy request and stores only its hash; the token stops being accepted once the deployment is not active anymore. - The runtime calls
PUT /api/liveData/deployments/{deploymentId}/collectors/{collectorId}withAuthorization: Bearer <token>. If the Designer sits behind an authenticating proxy (e.g. oauth2-proxy), that path has to be let through without user login. - Every uploading storage -
DESIGNER_DBas well asDESIGNER_API- now splits what it sends. The node counts and the throughput go up everyidleIntervalInSeconds(new forDESIGNER_DB, default 2), whether or not anybody has the scenario open, so they are available to any view that reads them. The live data samples - the records, expression results, service invocations and exceptions - are sent everyuploadIntervalInSeconds, but only while somebody watches the scenario. Reading a scenario's live data is what marks it as watched, for both storages. - Uploading the samples on demand is on by default for both uploading storages and can be turned off with
modelConfig.liveDataPreview.samplesOnDemand: false- the samples are then uploaded everyuploadIntervalInSecondsall the time, as before, and aDESIGNER_DBruntime doesn't readdeployments. TheDESIGNER_JVMstorage is not affected - its samples are always collected. The Lite runtime ignores the setting for now and always uploads the samples. - How the runtime learns that somebody watches a scenario differs by storage:
DESIGNER_APIis told in the response to each upload, whileDESIGNER_DBreadslive_data_watched_untilfrom thedeploymentstable. ADESIGNER_DBruntime therefore needsSELECTondeploymentsbesides its rights onlive_data; where it cannot read that column it keeps uploading the samples, as it did before, and says so in the log. - Switching an existing scenario type to
DESIGNER_APIrequires redeploying its scenarios - jobs deployed earlier have no token and don't upload live data. Scheduled (periodic) scenarios and thelite-k8sdeployment manager don't support this storage. Theflink-k8s-operatorandververicadeployment managers read it frommodelConfig.liveDataPreview.storageonly. - API changes:
DeploymentDatahas a newliveDataUpload: Option[LiveDataUpload]field (defaults toNone).LiveDataPreviewSupporthas a newLiveDataPreviewUploadedToDesignerApicase - exhaustive matches in custom deployment managers need to handle it.DeploymentManagerhas a newliveDataPreviewSupportFor(deploymentTarget)method, returningliveDataPreviewSupportby default.LiveDataCollectingListener.createListenerForhas a newliveDataUploadOptparameter.ModelConfig.LiveDataPreviewMode.Enabledhas a newsamplesOnDemand: Booleanfield (defaults totrue) - positional pattern matches on it need one more placeholder.GET /api/liveData/{scenarioName}responds with its ownLiveDataDtoinstead ofResultsWithCountsDto: it no longer has the always emptyassertionsResultsfield and has a newcountsOnlyfield,truewhen the live data holds the counts without the samples.
Code API changes
AnonymousAccessSupport,NoAnonymousAccessSupportandAuthenticatedUser.createAnonymousUserwere removed, along withanonymousUserRoleinAuthenticationConfigurationand in the basic auth, OAuth2, OIDC and dummy configurations.ImpersonationConsideringInputEndpoint.withPossibleImpersonationno longer takes theanonymousAccessEnabledflag.AuthCredentials.NoCredentialsProvidedwas removed: a request without credentials never reaches authentication. A customAuthenticationProviderthat implementedgetAnonymousRoleshould drop it.AuthenticationProvider.createAuthenticationResourcesandOAuth2ServiceFactory.createtake a furtheruserLookup: UserLookup;AuthenticationResources.impersonationSupportbecomesimpersonationTargets: Option[UserLookup].ImpersonationSupport,ImpersonatedUserData,UsersFileConfiguration,AuthenticationConfiguration.usersand the configurations'usersFile,getUserRolesandfindUserByIdare gone. Register aUserLookupFactoryto provide a store of your own. A customAuthenticationProvideralso has to answersignsInAgainstConfiguredAccounts-truewhere it checks passwords against the users file.- A users file entry setting both
passwordandencryptedPasswordnow fails the start under every authentication method. Keep one.
Other changes
- !1194 A database migration drops tables
the Designer no longer reads. Back up any of them you still need before upgrading:
process_actionsandprocess_comments- their data was copied toscenario_activitiesin version 1.18sticky_notes- sticky notes are stored in the scenario graph now, and notes from this table were never moved therescheduled_scenarios_orphaned_for_manual_reviewandscheduled_scenario_deployments_orphaned_for_manual_review(PostgreSQL only) - copies of scheduling data that pointed at deleted scenarios, kept for manual review
modelConfig.liveDataPreview.retentionTimecan be set tonullto turn off the age limit of the live data preview - onlymaxNumberOfRecordsthen limits what it keeps, for the records, expression results, service invocations and exceptions alike, however old they are. A missingretentionTimestill means 1 hour. It has to be an explicit HOCONnull, and it applies only whenretentionTimeInMinutesis not set.LiveDataPreviewMode.Enabled.retentionTimeis now anOption[Duration].GET /authentication/<method>/settingsno longer returns the frontend strategy at its top level. It returnsoptions, the ways of signing in -SingleSignOncarrying the former strategy understrategy,PasswordandAutoLogin- anddefault, either{"type": "Use", "option": <the option's type>}or{"type": "Chooser"}. The OAuth2 strategy no longer carriesanonymousAccessAllowed. Clients reading the strategy must look for theSingleSignOnoption;nu loginfrom an older CLI falls back to its browser snippet instead of driving the sign-in itself.
Designer deployment action metrics
!834 Designer deployment action timings are
now reported by a single tagged timer, deployments.action.duration, instead of the separate deployment, cancel
and singleExecution timers:
| Removed timer | Previously exported as | Replaced by |
|---|---|---|
deployment | metrics_deployment_* | operation="deploy" or operation="redeploy", stage="request" |
cancel | metrics_cancel_* | operation="cancel", stage="request" |
singleExecution | metrics_singleexecution_* | operation="run_off_schedule", stage="request" |
All three are now series of the same timer, for example designer_deployments_action_duration_count, told apart by
the operation and stage labels. stage="request" measures the command as a whole, as the removed timers did. The
new timer measures further stages - a cancel, for instance, is also measured per deployment target at
stage="execution" - and carries context tags such as scenario_name and deployment_target - see
Deployment action metrics for the full list.
The Designer JMX reporter now publishes in the designer domain instead of the default metrics one, so every
Designer JMX metric changes its exported prefix from metrics_ to designer_. The repository gauges, for example,
move from metrics_scenarios_count*, metrics_fragments_count* and metrics_deployedscenarios_count* to
designer_scenarios_count*, designer_fragments_count* and designer_deployedscenarios_count*. Lite JMX metrics
retain the metrics_ prefix.
The reporter also keeps the metric name as the first JMX key property. The Prometheus JMX exporter names a metric
after the first key property of its object name, which for a tagged metric would otherwise be an arbitrary tag - the
deployment action timer would be exported as designer_none_*, after its deployment_target="none" tag, with the
metric name demoted to a name label. The configured exporter lowercases label names; the new snake_case tag keys
are preserved as deployment_manager_type, deployment_target, scenario_id and scenario_name in PromQL
queries.
JMX Prometheus Java agent
!834 The bundled
jmx_prometheus_javaagent was upgraded from 0.20.0 to 1.6.0. Some automatically exported JVM metric names changed,
including jvm_memory_bytes_{committed,used,max,init}, which became jvm_memory_{committed,used,max,init}_bytes.
The agent now serves metrics at /metrics instead of /. Update clients that explicitly scrape the root path;
Prometheus configurations using its default metrics path do not need this change.
- !1030 The
ai-agentcomponent has a new parameterWhen an MCP server is unavailable, set toFail the eventfor existing nodes. When a tool call cannot reach its MCP server or times out, the event now goes to error handling; before, the failure was given to the model as the tool's result. To keep the previous behaviour, set the parameter toContinue without its tools. An error the tool itself returns is still given to the model.
In version 2.3-20260929-1
Configuration changes
- !1045 The component additional info provider
jar was renamed from
components/common/cloud-additional-info-provider.jartocomponents/common/additional-info.jar. AmodelConfig.classPaththat lists thecomponents/commondirectory needs no change. One that lists jars one by one must replace the old name - an entry pointing at the missing old jar fails the deployment. The same holds fordeploymentConfig.modelArtifact.providedJarFiles, which must stay in sync withmodelConfig.classPath. - !1047 The KV store component moved out of
components/common/enterprise-components.jarintocomponents/common/kv-store.jar. AmodelConfig.classPaththat lists thecomponents/commondirectory needs no change. One that lists jars one by one must addcomponents/common/kv-store.jar- without it a model configured with thekvStoreprovider fails to load. The same holds fordeploymentConfig.modelArtifact.providedJarFiles, which must stay in sync withmodelConfig.classPath. - !1015 The HTTP enricher moved out of
components/common/enterprise-components.jarintocomponents/common/http.jar. AmodelConfig.classPaththat lists thecomponents/commondirectory needs no change. One that lists jars one by one must addcomponents/common/http.jar- without it a model configured with thehttpprovider fails to load. The same holds fordeploymentConfig.modelArtifact.providedJarFiles, which must stay in sync withmodelConfig.classPath. cloud.websocket.urlandcloud.websocket.accessTokenmoved tocloud.websocket.read.urlandcloud.websocket.read.accessToken.- !990 The Designer no longer serves resources
under
/submodules: a request for/submodules/...now returns the Designer page instead of the file. Move a custom Module Federation remote fromweb/submodules/...toweb/static/...and change its URL intabsfrom/submodules/...to/static/.... The Configurator and MCP tabs are nownuEnterpriseIntegrations/tab@/static/integrations/remoteEntry.jsandnuEnterpriseMcp/tab@/static/mcp/remoteEntry.js. The Designer rewrites the oldnuConfigurator/*tab URLs to these automatically. - !979 The scenario migrations (
DefaultModelMigrations) moved out ofmodel/defaultModel.jarintomodel/migrations.jar, so that a model built on a differentProcessConfigCreatorpicks up the same migrations. Nothing listsmodel/as a directory, so everymodelConfig.classPaththat listsmodel/defaultModel.jarmust addmodel/migrations.jarexplicitly - without it no migration is applied and the model version drops to 0. The same holds fordeploymentConfig.modelArtifact.providedJarFiles, which must stay in sync withmodelConfig.classPath.
Code API changes
- !1067 The
TestProcess.TestResultsmethodsupdateNodeResult,updateNodeOutputResult,updateExpressionResult,updateExternalInvocationResultandupdateExceptionResultare removed. UseResultsCollectingListenerHolder.withListenerfor raw values orResultsCollectingListenerHolder.withTestEngineListenerfor JSON values, pass events to the listener's callbacks, and readlistener.resultsafter collection. UseTestServiceInvocationCollectorwith that listener for service and sink invocations. These collectors are inpl.touk.nussknacker.engine.testmodeinnussknacker-scenario-compiler.
Lite metric reporter lifecycle
!1065
MetricsReporter.createAndRunReporter now returns AutoCloseable instead of Unit. Recompile custom Lite metric
reporters and return a handle that stops the reporter and releases its scheduler, connections and metric listeners.
The runtime owns that handle and closes it on shutdown or if a later startup step fails. If the reporter throws before
returning its handle, it must clean up any resources it already acquired itself.
LiteMetricRegistryFactory.prepareRegistry now takes the classloader to discover and run the reporters with, and
returns LiteMetricRegistry instead of MetricRegistry - an AutoCloseable exposing the Dropwizard registry as
.registry, whose close() stops the reporters started for it.
Other changes
- !973 Fix scenarios failing on a null
aggregateBy, and returnnullfrom a numeric aggregate that aggregated nothing, in place of0orDouble.NaN:- State incompatibility:
aggregate-tumblingandaggregate-sessionnodes have to be redeployed with their state reset.aggregate-sliding, theaggregate-tumbling"After window closes, also when no event for key" emit mode,single-side-joinandfull-outer-joinare unaffected. #AGG.average,#AGG.median,#AGG.stddevPop,#AGG.stddevSamp,#AGG.varPopand#AGG.varSampreturnnullinstead ofDouble.NaN;#AGG.sumreturnsnullinstead of a typed0. ReplaceisNaN()checks with null checks, and use#aggregate == null ? 0 : #aggregatewhere a number is required.- Arithmetic on a
nullaggregate fails at runtime, but a comparison does not:#aggregate > 100isfalseand#aggregate < 100istrue. Guard both, for example#aggregate != null && #aggregate > 100. - Counting with
#AGG.sumover1now answersnullfor a window that counted nothing. Switch it to#AGG.countWhenovertrue. aggregate-slidingstores the first0of a slice, which it skipped before. A scenario whoseaggregateByis mostly0grows its state, and with "emit when event leaves the window" it now also emits for a key that only ever saw zeros.pl.touk.nussknacker.engine.api.typed.NumberTypeUtilsis removed.
- State incompatibility:
- !1050 In
flink-components-utils, the key parameter of thekeyedmappers (KeyedValueMapper,GenericKeyedValueMapper,StringKeyedValueMapper,StringKeyOnlyMapper,GenericKeyOnlyMapper) and of therichflinkgroupBy,groupByKeyandgroupByWithValueis aParameterNameWithLabelinstead of aParameterName. PassparamNameWithLabelof the key parameter's declaration, orParameterNameWithLabel(name, label).
Parameter descriptors extracted into named constants
No parameter name changed, so stored scenarios need no migration.
- Where the text of a validation error names a parameter, it now uses the parameter's label instead of its technical
name, e.g. in the
'<label>' -prefix of the plain-text errors returned by the testing API. Labels changed across most components, so update clients that match on this text. - Component parameter constants are now
UpperCamelCasewith aParamNamesuffix and hold aParameterNamerather than aString. Some moved or are gone: the Kafka names live inKafkaParameters(kafka-components-utils) andSchemedKafkaParameters(schemed-kafka-components-utils),KafkaFactoryandWatermarkStrategyValidationHandler.splitNamewere removed, and the label constants are private. Take a label from the matchingparamNameWithLabel. KafkaUniversalComponentTransformernow matches the topic parameter by name. A subclass that renames that parameter must overridetopicParamNamealongsidetoTopicParamDeclaration; the name was previously ignored.
In version 2.3-20260921-1
REST API changes
- !894 Validation errors changed:
messagewas reworded and now carries the remedy that used to sit indescription. Clients that match on the exact text of a message need updating.descriptionofNodeValidationError,EnricherMockValidationErrorandAssertionValidationErroris optional: it is notrequiredin the OpenAPI document and isnullwhen absent. Clients that read it must handlenull, clients that build it can omit it.messagestays required.descriptionis nownullwhere it used to be:- an empty string, e.g. for
MultiSelectInvalidFormator a validator that gave"", - a copy of
message, forCustomNodeErrorandEagerExpressionEvaluationError, Enter a value in this field, forEmptyMandatoryFieldand for an empty scenario name, fragment name, node name or node id.
- an empty string, e.g. for
Code API changes
- !894 Validation errors changed:
descriptionis nowOption[String]inParameterValidationErrorand every case class inProcessCompilationErrorthat extends it (e.g.CustomParameterValidationError), inCompileTimeAndRuntimeValidatorandRegExpValidator, and in the REST model classesNodeValidationError,EnricherMockValidationErrorandAssertionValidationError. UseSome(text), orNonewhere you used"".messagestays aString, andScenarioNameValidationErrorandScenarioLabelValidationErrorkeep aStringdescription. Existing JSON and HOCON configuration ofRegExpValidatorstill works, anddescriptionin it may now be omitted ornull.NonNegativeDurationValidation.DescriptionandPositiveDurationValidation.Descriptionwere removed, with no replacement - drop the reference. BothMessagevals stay, with reworded text.- The first field of
ProcessCompilationError.NonUniqueEdgeTypeand ofProcessCompilationError.UnsupportedEdgeNextToCustomNodeOutputswas renamed fromedgeTypetooutputName. It now carries the output label the graph shows instead of theEdgeTyperendered throughtoString. Update named arguments and named pattern bindings; positional construction and pattern matches are unaffected. - A node other than
splitwith more than one unnamed outgoing edge is now rejected withNonUniqueEdgeType("main", ...)instead ofNonUniqueEdgeType("main output", ...).
In version 2.3-20260915-2
In version 2.3-20260915-1
Artifacts are published to internal repositories only
- Maven artifacts are published exclusively to
nexus.touk.pl. Snapshots are no longer published to Maven Central (central.sonatype.com). - The ML modules changed their Maven organization from
pl.touk.nussknacker.mltopl.touk.nussknacker. - Docker images (
nussknacker,nussknacker-lite-runtime-app) are published todocker-gitlab.touk.pl/nussknacker-cloud/dummy-for-docker-registry/instead of DockerHub (touk/...). - The default
dockerImageNameof thelite-k8sdeployment manager changed fromtouk/nussknacker-lite-runtime-apptodocker-gitlab.touk.pl/nussknacker-cloud/dummy-for-docker-registry/nussknacker-lite-runtime-app. The registry is private, so the runtime pods need image pull secrets (configured viak8sDeploymentConfig). SetdockerImageNameexplicitly if your cluster should pull the runtime image from somewhere else.
License key is now required
The Designer now reads a signed license key from the licenseKey configuration entry (or the NU_LICENSE_KEY
environment variable). See License key for details.
- An installation without a valid key loses access to every component delivered by a component provider. Such components stay visible in the creator panel but are locked: they cannot be dragged onto the canvas, scenarios using them fail validation and cannot be deployed. Built-in components (filter, choice, variable, split, ...) and fragments keep working. Scenarios already running on the cluster are not touched.
- Before upgrading, obtain the license key issued for your installation and add it to the Designer configuration:
licenseKey: "<the key>"(or setNU_LICENSE_KEY). A malformed key stops the Designer at startup with an error in the log; a missing or expired key keeps the Designer running with all provider components locked and a banner explaining why. - Component and provider names use separate allowlists. Entries in
componentsmatch only component names (either unqualified or asproviderName/componentName); entries in the optionalproviderslist match only provider names. When replacing a key created with an earlier preview of this feature, move provider-level entries such asflink*fromcomponentstoproviders. The specialcomponents: ["*"]entry continues to unlock every component. - Code constructing
ModelDependenciesmust now pass its component licensing policy explicitly. UseComponentLicensing.Unrestrictedonly where license enforcement is intentionally not applicable; the Designer passes aComponentLicensing.Restrictedpolicy derived from the verified license key.
Deployment status mechanism
The scenario status is now resolved from the deployments table (kept fresh by the deployments statuses synchronizer)
instead of being derived by merging the action log with the engine state. A deploy/redeploy now stores a deployment row
with a stable id (periodic scenarios are the exception - they keep their own scheduling mechanism and are not
represented in the deployments table). On Flink this id is used as the job's JobID, so the synchronizer can correlate
the running job with the stored status; lite-k8s stores it as a k8s Deployment annotation.
- Existing running jobs have to be redeployed or canceled once. Jobs deployed before this version were started with
the old deployment id scheme, so they are not correlated with the new deployments table. After the upgrade such
scenarios are shown with a
PROBLEMstatus with the message "The scenario was deployed before an upgrade and its status is no longer tracked. Redeploy it to restore tracking or cancel it to stop the old job. Redeploy will replace the running job, preserving its state." — this is intentional so that a still-running job is not mistaken for a stopped one (which could lead to losing its state). Such scenarios are also counted as active for deployment limits until they are resolved. Redeploy each scenario that should keep running; the redeploy replaces the orphaned job, preserving its state via savepoint. Cancel scenarios that are no longer needed. After redeploy or cancel the status is tracked normally and the message disappears. - For
lite-k8s, the deployment id is stored as anussknacker.io/deploymentIdannotation on the scenario's k8s Deployment (metadata only, so it does not trigger a pod rollout). - The deployments table is periodically cleaned up: final-status rows (
CANCELED/FINISHED/PROBLEM) older thandeploymentStatusesSynchronization.keepFinalDeploymentsFor(default 24 hours) are deleted, except the newest final row of each scenario. Use the scenario activities for deployment history. The cleanup runs everydeploymentStatusesSynchronization.cleanupInterval(default 1 hour).
Deployment targets
-
A scenario type can be served by several deployment managers at once, one per deployment target. Such a scenario type has no
deploymentConfig.type; it lists its targets indeploymentConfig.targetsinstead:deploymentConfig {
targets: [
{
# The first target is the default one - it is where the commands that don't point at any target go.
name: "Standalone Flink"
type: "flinkStreaming"
restUrl: "http://jobmanager:8081"
useMiniClusterForDeployment: false
}
{
name: "Flink MiniCluster"
type: "flinkStreaming"
useMiniClusterForDeployment: true
}
]
}A
targetsentry is the deployment configuration of the manager handling that target,typeincluded, plus aname- the deployment target name shown in the designer, which has to be unique. The targets are presented in the configured order, and the first one is the default.targetsandtypeare mutually exclusive, and every entry oftargetsconfigures a single Deployment Manager, so targets cannot be nested. A scenario type configured withtypekeeps behaving exactly as before: one Deployment Manager, no deployment targets. -
All the targets of a scenario type share its model and the resources bound to it - in particular, Flink targets share a single MiniCluster, the same one used for scenario testing and state verification. Periodic scheduling wraps a whole Deployment Manager, which has no notion of per-deployment targets, so a scenario type split into targets reports no scheduling support. A target that runs scenarios outside the designer's JVM still needs
modelConfig.liveDataPreview.storageto beDESIGNER_DBfor live data preview; that requirement is now reported per target. -
Deployment targets can also be created, changed, reordered and removed at runtime - see the configuration docs. New DB migration
V1_076: thedeployment_targetsanddeployment_target_ordertables, and a nullabledeployment_targetcolumn indeployments. -
A scenario can only change its deployment target while it has no deployment that may still exist on an engine (anything but
CANCELED/FINISHED) - each target is backed by its own engine and only replaces its own deployments, so cancel the scenario first. For the same reason, a target cannot be removed while a scenario may still be running on it, and a scenario whose recorded target is no longer configured cannot be deployed at all. -
A scenario that is running when you upgrade cannot change its deployment target until it is cancelled. Deployments created before this version have no target recorded, so it is not known which engine runs them. The designer fills the target in where it can: on startup, scenario types that recover jobs ask their engines. Cancelling such a scenario is sent to every configured target (engines treat cancelling a scenario they do not run as a no-op), but the admin-only
POST /api/adminProcessManagement/stop/{name}and.../snapshot/{name}cannot fan out that way and are rejected with an explicit error. -
Source-breaking changes for code compiled against Nussknacker's API modules:
- The
DeploymentManagerSPI gained adeploymentTargetsSupportmethod. It defaults toNoDeploymentTargetsSupport, the previous single-target behavior, so existing implementations need no change. DeploymentManagerProvidergained adeploymentTargetType(config)method declaring the one kind of target the provider serves when configured with the given config, and which can therefore be created at runtime. It defaults toNone, so existing implementations need no change.DeploymentSynchronisationSupported.getCurrentDeploymentStatusesnow returnsDeploymentStatusesFromEngineinstead of a bareMap[DeploymentId, DeploymentStatus]. Wrap the map you returned before - the companion's single-argumentapplyreports no unreachable targets, which is right for a single-engine manager.- The
LiveDataPreviewSupporthierarchy gainedLiveDataPreviewStoredInDesignerJvmOrDb, reported when some targets store live data in the designer's JVM and the others in its database. Matches over it have to handle the new case. - Every scenario command that acts on a running job carries the deployment target it is meant for:
deploymentTarget: Option[DeploymentTarget]was added toDMCancelScenarioCommand,DMStopScenarioCommand,DMMakeScenarioSavepointCommand,DMCancelDeploymentCommandandDMStopDeploymentCommand, next to theDMRunDeploymentCommand/DMValidateScenarioCommandfields that had it already. A Deployment Manager serving several targets routes on that field inprocessCommand, soDeploymentTargetsSupported.processCommandForTargetis gone - send the command itself instead. - New fields breaking exhaustive pattern matches over the case classes (construction stays source-compatible where
the field defaults to
None):DMRunDeploymentCommand.deploymentTarget,DMValidateScenarioCommand.deploymentTarget,ProcessStateDefinitionManager.ScenarioStatusWithScenarioContext.deploymentTargetandDeploymentStatusDetails.deploymentTarget.ScenarioActivity.ScenarioDeployed/ScenarioRedeployed,DeployRequest(restmodel) andUIDefinitions(restmodel) gained required fields, which breaks construction too, as do the constructors ofCachingProcessStateDeploymentManagerandEmbeddedDeploymentManager. FlinkDeploymentManagertakes aSharedFlinkMiniClusterwhere it took aFlinkMiniClusterWithServices, andFlinkMiniClusterScenarioJobRunnergained a required constructor parameter. Acquire the cluster withSharedFlinkMiniClusters.acquire(modelClassLoader, miniClusterConfig)and close the handle it returns when the manager is closed.- The embedded engine treats cancelling a scenario it does not run as a no-op instead of failing. This applies to
plain
lite-embeddedtoo, and a caller that relied on the failure to detect an unknown scenario no longer gets it. ScenarioStatusDetailsDto(restmodel) gained aDuringDeploysubtype. Every scenario status JSON gained a nullabledeploymentTargetfield - not only the ones of a scenario that is being deployed or is running.
- The
Authentication
- !519
OidcAuthenticationConfigurationgained anenableBasicAuthForTechnicalAccountsoption, defaulting tofalse. When enabled, users in the OIDCusersFilethat have apassword/encryptedPasswordset can additionally authenticate via HTTP Basic - intended for technical/machine accounts that cannot go through the OIDC flow (for example theRemoteEnvironmentscenario-migration client). OIDC-only users, which have no password, are unaffected. Existing configurations keep OIDC-only authentication.
Authorization decisions go through AuthorizationService
Authorization moved from the Read/Write/Deploy permission bundles to per-action grants. The users file is
unchanged - its permissions still expand to the same actions - but what the API reports, and what a few
endpoints require, did change.
Behaviour
- Deleting a scenario (the API-only
DELETE /api/processes/{name}, available for archived scenarios) now requires admin - previously any role with theWritepermission in the scenario's category could delete it. It is also out of reach of an impersonated session, even one impersonating an admin. - Endpoints returning records read off a scenario's sources now require
Scenario.ViewLiveDataandScenario.Test:POST /api/nodes/{scenarioName}/records, which had no authorization of its own at all,POST /api/scenarioTesting/{scenarioName}/generatedTestData, andperformTestwhen the request carriesWITH_LIVE_DATA. The source to read from is named by the request rather than taken from the stored scenario, so the grant on the scenario in the URL does not bound which records come back.Scenario.Testcomes from theDeploypermission, so roles holding onlyReadorWritelose these endpoints. - Impersonating an admin (possible only with
isAdminImpersonationPossible) no longer grants admin-only endpoints: the impersonated session keeps the admin's category-wide data access, butAdminAccessnow reflects the real session's identity. Chained impersonation (impersonating from an already impersonated session) remains impossible.
HTTP API
/api/userreplacescategoryPermissions/globalPermissionswithcategoryActions/globalActions, listing full"<Resource>.<Name>"action identifiers (Scenario.Deploy,Core.Impersonate, and config-authored permissions asCustom.<name>), and adds arolesfield naming the roles the identity carries.isAdminstays, mirroringCore.AdminAccessinglobalActions. Both lists are filled for an admin as well, where the old fields came back empty for one. External API clients must update to the new field names and identifier format.- Global permission names are matched case-insensitively throughout: they appear in
/api/usercanonicalized to lowercase, and/api/settingsnormalizes tabs'requiredPermissionthe same way. A client comparing these against the config-authored casing must switch to a case-insensitive comparison (the Designer frontend already does). ScenarioTestCapabilities(POST /api/scenarioTesting/{scenarioName}/capabilities) gainedtestWithProvidedData, for running a test on records the caller supplies - it needs neither a parameter form nor the right to read a source, which neither existing entry expressed.testWithLiveDatanow reports the fullTest+ViewLiveDatapair, so a caller holding one but not the other is told beforehand instead of being refused on the following request.
Code compiled against the API
AdminUser,CommonUserandRulesSetare removed.LoggedUseris now a pure identity carrying no permission data:RealLoggedUser(id, username, roles),ImpersonatedUser, or the internalSystemUser.LoggedUser.can(category, permission),CommonUser.categories/categoryPermissionsandRulesSet.permissionsare gone with them - authorization decisions go entirely through the newAuthorizationService:check(action, scope)/checkGlobal/checkInCategoryfor a single decision, andvisibleCategoriesfor enumeration.AuthenticationProvider.createAuthenticationResourcesgained a third parameter,infrastructure: SecurityInfrastructure- any customAuthenticationProviderimplementation must update its signature accordingly.AuthenticationConfigurationno longer declaresisAdminImpersonationPossiblenorrules- theauthentication.isAdminImpersonationPossibleconfig key and the users file'srulessection keep working (the Designer reads them itself), but a customAuthenticationConfigurationoverriding those members must drop the overrides.NussknackerServicesForCustomHttpServicenow carriesauthorizationService: AuthorizationService,actionCatalog: ActionCatalogandclock: java.time.Clock- custom HTTP service providers should useauthorizationServicefor authorization decisions instead of interpretingLoggedUserthemselves. Code constructing this class must supply all three new fields.CustomHttpServiceProviderFactorydeclaresprovidedActions: List[ResourceAction], the actions its endpoints check - every factory has to implement it, withList.emptywhere there are none. Resource names may not collide across extensions, and the Designer refuses to start if they do.- An authorization backend other than the users file is supplied by implementing
AuthorizationRulesand registering anAuthorizationRulesFactoryfor theServiceLoader. Itscreatereceives the installation'sActionCatalog, assembled from those declarations before the authorization service exists and fixed for the life of the process. Every action the backend evaluates has to be inactionUniverse, which it builds from that catalog: one missing from it is denied under impersonation and absent from/api/user, whatevercheck()answers.
New CanonicalNode subtype for per-node error-recovery edges
- !359 The per-node error-recovery output edge adds a new
canonicalnode.FlatNodeWithError(data, nextError)case to thesealed CanonicalNodehierarchy. Any code that pattern-matches exhaustively overCanonicalNodewithout a default case (for example a customProcessMigrationthat rewrites the canonical graph) must add a branch forFlatNodeWithError; otherwise it will fail to compile withmatch may not be exhaustiveonce built against this version.
Module Federation scope of the components frontend renamed
- The container scope of the components frontend was renamed from
nu_componentstonuComponents, so that it is derived from the package name like every other remote. The defaultcomponentsAppUrl/scenariosAppUrlwere updated accordingly. No action is required for existing configs: a tab url still using the old scope is mapped to the current one by the Designer frontend. If you override these urls (directly in your config or through theNU_FE_COMPONENTS_URL/NU_FE_SCENARIOS_URLenvironment variables), update the scope -nu_components/list@...tonuComponents/list@...andnu_components/scenarios@...tonuComponents/scenarios@...- because that mapping rewrites the whole url to the standard/static/components/remoteEntry.jsmount, dropping a custom location.
Flink state and API compatibility
Flink state will be incompatible because of multiple changes that involve state serialization, main of which are:
- updated Kryo serialization library in Flink 2.0
- changes in typing for lists, maps and sets in Flink 2.0
- various code changes in Nussknacker
Refer to Flink release notes for detailed Flink API changes.
Request-Response interaction (pause/resume) support
- Request-Response scenarios can now pause at an
interactionnode and be resumed later via a new/resumeendpoint, secured the same way as the main invocation endpoint (ifrequest-response.security.basicAuthis configured,/resumerequires it too - a validcontinuationIdalone is not enough). A scenario with one or moreinteractionnodes now compiles into several interpreters internally (one for the main flow, one per resume point); this is transparent to scenario authors but is worth knowing when reasoning about deployment/compilation time or per-node metrics for such scenarios. - New
request-response.continuationMaxCacheSizeconfiguration entry (default100000) bounds the number of paused continuations kept in memory at once, independent ofcontinuationTtl- a burst of interactions can no longer grow the cache unboundedly before entries expire. Tune it down for memory-constrained deployments, or up if continuations legitimately spike higher. - Metrics for a scenario using interaction nodes are not scenario-version-scoped (a redeploy continues the same metric series rather than starting a new one), but a resume interpreter's metrics carry an additional
resumeInteractionNodeIdtag so they don't collide with the main flow's metrics for the same node id. - A metric registered by more than one live interpreter of the same scenario - which happens while a redeployed version is still draining - is now kept until every one of them has been closed, and a gauge registered by the newer interpreter takes over from the draining one's. Registering the same gauge name twice from a single interpreter is still an error, as before.
- When the paused-continuation cache is full, the dropped continuation is logged at
WARNby the runtime (naming the scenario, the interaction node and thecontinuationId), and a later/resumecall for it responds400with a message listing why acontinuationIdmay not be resumable (never issued, already resumed, expired, or dropped because the cache was full). The same400replaces the previous, terser "Unknown or invalid continuationId" message for every unrecognisedcontinuationId. - A
continuationIdis consumed atomically, so two/resumecalls with the same one - including two arriving concurrently - resume it at most once: exactly one of them runs the scenario, the other gets a400saying the continuation is no longer resumable. Treat/resumeas non-idempotent: retrying it after a timeout may find the continuation already consumed rather than re-running it. - An environment that does not want pause/resume at all can hide the component instead of relying on scenario authors, by disabling it in that environment's model configuration:
componentsUiConfig.interaction.disabled: true. - Resume support differs by engine - it is not equally reliable everywhere:
- Embedded engine (
EmbeddedDeploymentManager/RequestResponseDeploymentStrategy) - fully supported. Newrequest-response.continuationTtlconfiguration entry (default5 minutes) bounds both how long acontinuationIdstays resumable and how long a redeployed or stopped scenario version keeps its/resumeendpoint alive for already-paused continuations ("draining") before being fully shut down. The main invocation endpoint (/) stops accepting new requests as soon as a scenario is redeployed or stopped - only/resumeis kept alive, for up tocontinuationTtl. Draining applies only to scenarios that actually contain aninteractionnode: one without any resume point is torn down immediately on cancel/redeploy, exactly as before, rather than being held forcontinuationTtl. A redeploy drains correctly whether or not it changes the scenario version - every live version of a scenario serves the same/resumepath, and acontinuationIdis matched against every live interpreter for the scenario (it is an unguessable, single-use UUID, so the caller does not need to say which version issued it). - Kubernetes (
lite-k8s) - no draining, and resume is reliable only with a single replica. There is no equivalent of the embedded engine's draining window: cancelling a scenario tears down its Deployment/Service immediately (K8sDeploymentManager.cancelScenario), with no grace period for in-flight continuations, so any/resumecall after that fails once the pods terminate. Redeploying instead relies on plain Kubernetes rolling-update behavior: the old pod keeps serving both/and/resumeuntil Kubernetes sends it SIGTERM (governed byterminationGracePeriodSeconds, 30s by default; there is noPreStophook delaying shutdown for pending resumes), so a continuation not resumed within that window is lost regardless ofcontinuationTtl. Separately, the paused-continuation store is per-pod and in-memory and the Service has no session affinity, so with more than one replica/resumecalls routed to a different pod than the one that issued thecontinuationIdfail unpredictably - deploy scenarios usinginteractionnodes with a fixed replica count of1(e.g. viaFixedReplicasCountK8sScalingOptionsDeterminer; not enforced automatically, but the designer logs a warning when deployed with more than one replica). Treat/resumeon k8s as best-effort around deploys and cancels until graceful draining is implemented there.
- Embedded engine (
Request-Response collect is now a join and union was removed
- !386 In the Request-Response processing mode,
collectchanged from a single-input component into a join, andunionis no longer available there. An automatic migration replaces theunion+collectshape with a singlecollectjoin. If a scenario still fails to compile after the upgrade, replaceunion+collectwith a singlecollectjoin manually. unionitself is unchanged in the Lite streaming (Kafka) and Flink processing modes; only its availability in Request-Response was removed.
Request-Response sources support HTTP methods
- !500 The
requestsource has a newmethodparameter (POST,GET,PUT,DELETE,PATCH), defaulting toPOST. Existing scenarios keepPOSTand the slug stays a scenario property, so no scenario migration is needed. - !640 Request-response:
queryParametersnow works with every method - for body methods the values are merged into#input(names must not collide withinputSchemaproperties); new scenarios start with an empty-objectinputSchema. Code API: slug helpers moved to the newRequestResponseSlug(common-api), the body/query-params source traits are replaced byRequestResponseSource.parse(IncomingRequest)(a former query-params source declaresmethod = Getitself),OpenApiSourceDefinitioncarriesbodySchema/queryParametersSchema. GETandDELETEtake their input from query parameters;POST,PUTandPATCHread a JSON body. RFC 9110 leaves content inGETandDELETErequests without defined semantics and intermediaries are free to drop it, so a body is not read for them.- For
GETandDELETEthe input is described by a newqueryParametersparameter on therequestsource instead of theinputSchemascenario property, because only the source knows the method. It accepts a flat object of scalars and lists of scalars - nested objects, lists of objects and nullable or union-typed fields are rejected when the scenario is saved, since a query string cannot express them. - Custom Request-Response sources:
RequestResponsePostSource[T]was renamed toRequestResponseBodySource[T]andRequestResponseGetSource[T]toRequestResponseQueryParamsSource[T](whoseparsenow returnsRequest[T]instead ofRequest[Any]). Sources now exposedef method: RequestResponseHttpMethod(defaults toPOST). - A custom source serving a method other than
POSTmust also expose it as amethodnode parameter holding a string literal (as the built-inrequestsource does), because everything that documents the endpoint - the OpenAPI definition and the Designer's Integration section - reads the method off the scenario graph. A source whosedef methoddisagrees with the graph declaration fails at scenario start with an explicit error, since the generated documentation would otherwise describe a method the endpoint does not serve. - A Request-Response scenario's effective slug (the explicit slug, or the one derived from the scenario name) must now be unique among non-archived scenarios of the same processing type. Saving or migrating a scenario whose slug is already taken is rejected; existing scenarios with duplicate slugs stay loadable, but their next save requires a unique slug. Previously two scenarios could hold the same slug as long as they were not deployed at the same time.
Evictable state API of Flink components
- !112 !135 !435 !600 #7553 The evictable state API was reworked and moved from
pl.touk.nussknacker.engine.flink.api.statetopl.touk.nussknacker.engine.flink.api, so every import of it has to be updated. Custom Flink components extending it need the following adaptations:LatelyEvictableStateFunctionis no longer a class but a trait, and it no longer implementsonTimer. The abstract classes of the family -EvictableStateFunction,LatelyEvictableStateCoFunctionand the previousLatelyEvictableStateFunction- are gone, together withStateHolderandLatelyEvictableStateFunctionMixin, whose members live on across the trait ladder below. What is left is a ladder of traits:LatelyEvictableFunction(the eviction deadline and its single timer per key),LatelyEvictableStateFunction[StateType](the above plus oneValueState),LatelyEvictableKeyedProcessFunction[Key, In, Out](the eviction machinery on aKeyedProcessFunctionbase, withonTimerwired for you) andLatelyEvictableStateKeyedProcessFunction[Key, In, Out, StateType](all of the above combined). They live inLatelyEvictableFunction.scala, previouslyEvictableState.scala. A component extendingEvictableStateFunctionalso moves to the combining trait - mind that this is not behaviour-preserving: the oldmoveEvictionTimeregistered a timer on every call and overwrote the recorded eviction time unconditionally, moving it backwards included, whilemoveEvictionDeadlineToonly moves the deadline forward and registers a timer only when none is pending. With out-of-order events the state now lives until the latest deadline rather than the last-written one.- A component that used to extend
LatelyEvictableStateFunction[In, Out, StateType](the key was hardcoded toString) extends the combining trait instead, which is the closest equivalent:class MyFunction extends LatelyEvictableStateKeyedProcessFunction[Key, In, Out, StateType] {
// stateDescriptor and processElement unchanged
} - A component whose Flink base is not a
KeyedProcessFunction- aCoProcessFunction, say - mixes the granular traits into that base and wires the timer by hand:Omitting thatclass MyCoFunction
extends CoProcessFunction[In1, In2, Out]
with LatelyEvictableStateFunction[StateType] {
override def onTimer(timestamp: Long, ctx: CoProcessFunction[In1, In2, Out]#OnTimerContext, out: Collector[Out]): Unit =
handleOnTimer(timestamp, ctx.timerService())
// stateDescriptor and processElement1 / processElement2 unchanged
}onTimercompiles and fails silently -CoProcessFunction.onTimer(likeKeyedProcessFunction.onTimer) is a concrete no-op, so eviction timers fire and evict nothing, and the state grows without bound. This is why theKeyedProcessFunctioncase has a trait that wires it for you. - Timer registration and current-time resolution live in the new
WithTimeModeandKeyedProcessFunctionWithTimeMode[Key, In, Out]traits, which the ladder mixes in.KeyedProcessFunctionWithTimeModedeclaresprotected type FlinkCtxandprotected type FlinkTimerCtx; a class declaring its own alias under either of those names needs theoverridemodifier.LatelyEvictableStateKeyedProcessFunctioncarries those aliases too, since it mixes that trait in. moveEvictionTime(offset, ctx)is gone; callmoveEvictionDeadlineTo(currentTime(ctx) + offset, ctx.timerService()), which takes an absolute deadline rather than an offset. In a function withoutKeyedProcessFunctionWithTimeMode(theCoProcessFunctioncase above) there is nocurrentTime- usectx.timestamp() + offset, which is the same thing in the default event-time mode.doMoveEvictionTime(time, timeService)becamemoveEvictionDeadlineTo(deadlineTimestamp, timerService); only the name changed.- Eviction timers are registered according to
def timeMode(EventTime/ProcessingTime), which defaults toEventTime, so a component that does not override it keeps its previous event-time eviction. Override it to evict in processing time - and then compute deadlines fromcurrentTime(ctx)rather thanctx.timestamp(), so the deadline and the timer live in the same time domain. evictStates()was replaced byclearAllState(), and clearing the eviction deadline moved to the caller.LatelyEvictableStateFunctionimplements it as afinalmethod -state.clear()followed by the newclearAdditionalState()hook - so a subclass that used to overrideevictStates()to drop extra state on top of the basestate(like a counter of its own) overridesclearAdditionalState()instead, with nosupercall to remember. On the bareLatelyEvictableFunctionthe method is abstract: a component built directly on that rung is forced by the compiler to say what eviction drops.clearStateOlderThan(timestamp)- dropping the part of the state that a fired timer made unreachable - defaults to a no-op, which is what a state that lives and dies with the deadline needs. A state holding per-timestamp entries (the aggregator's buckets, say) overrides it and derives its own cutoff.readState()was removed - read the state directly withstate.value().latestEvictionTimeForKeyis no longerprotected. Read the current deadline withprotected def evictionDeadline: Option[Long]; move it withmoveEvictionDeadlineTo.AggregatorFunctionMixin[MapT]becameBucketedAggregatorFunction: no type parameter, noStateHolderself-type, and it no longer evicts - it manages the aggregate buckets and nothing else, on a bareRichFunction. The buckets live behind the protectedbucketsState(aBucketsStatewrapping aMapStatewith the buckets and aValueStatewith the sorted list of bucket timestamps), set up byBucketedAggregatorFunction.open, so an extending class only chainssuper.open(openContext). This state layout change is savepoint-incompatible for aggregates, as its Changelog entry notes. Its members changed with it:- the implicit
rangeMap: FlinkRangeMap[MapT]member is gone, andFlinkRangeMapitself was deleted; addElementToStatereturnsUnitinstead of the new map and gained a[K <: AnyRef]type parameter;computeFinalValue(newState, timestamp)becamecomputeFinalValue(timestamp, keys);minimalResolutionMsis avalderived from the window length instead of a fixeddef = 60000;AggregatorFunctionitself lost[MapT]and the implicit parameter list, gainednodeName, and takesKeyedValue[AnyRef, AnyRef]instead ofStringKeyedValue.
- the implicit
- Eviction of the buckets comes in three shapes:
LatelyEvictableKeyedProcessFunctioncombined withLatelyEvictableBucketedAggregatorFunction- deadline-driven eviction withonTimerwired for you (AggregatorFunction,FullOuterJoinAggregatorFunction);LatelyEvictableBucketedAggregatorFunctionon a hand-picked base with a hand-writtenonTimercallinghandleOnTimer- when the timer also does other work or the base is not aKeyedProcessFunction(EmitWhenEventLeftAggregatorFunction,SingleSideJoinAggregatorFunction);- the bare
BucketedAggregatorFunction- when the function drives eviction entirely from its ownonTimerviaclearBucketsOlderThan/bucketsState.clear()(EmitExtraWindowWhenNoDataTumblingAggregatorFunction).
Lifecycle traits of Flink functions are stackable
- !600 The traits that hook into a Flink function's lifecycle -
LazyParameterInterpreterFunction,SingleLazyParameterFunction,LatelyEvictableFunction,LatelyEvictableStateFunction,BucketedAggregatorFunction,StatefulFunction- declareopen(andclose, where they have one) asabstract overrideand chain tosuper.LazyParameterInterpreterFunctiontakesRichFunctionas a supertype rather than a self-type, which is what makes that chaining possible. Theopen/closeofLazyParameterInterpreterFunctionand of the evictable-state family used to be terminating overrides, so a component mixing both families had to invoke each of them by name.- A component that combined them like this:
now writes
override def open(openContext: OpenContext): Unit = {
super[LatelyEvictableStateFunction].open(openContext)
super[LazyParameterInterpreterFunction].open(openContext)
}super.open(openContext)once, and anopen/closeoverride that did nothing else can be dropped entirely. The qualified form keeps compiling, but it now runs the rest of the chain twice - replace it rather than leave it. - A component that overrides
openorcloseand does not callsuperno longer initialises (or releases) what these traits own. That was already true, but it is now the single thing to get right. abstract overriderequires a concreteopen/closefrom a base class in the linearization. Mixing one of these traits into a class extendingAbstractRichFunction(soKeyedProcessFunction,CoProcessFunction,RichFlatMapFunction, ...) satisfies that - Flink 2.x leavesRichFunction.open/closeabstract and implements them inAbstractRichFunction. Intermediate traits still compile; a concrete class that mixes one of these traits without such a base fails withclass X needs to be a mixin. ... is marked 'abstract' and 'override', but no concrete implementation could be found in a base class.
- A component that combined them like this:
OneParamLazyParameterFunctionwas renamed toSingleLazyParameterFunction, andAbstractOneParamLazyParameterFunctiontoAbstractSingleLazyParameterFunction. Apart from theopen/closechanges described above, signatures are unchanged.
Named outputs for custom components; deduplication rejected output
!625 Custom components declare their outputs as one ordered list (head = main output); deduplication declares passed and rejected. A custom node of such a component is stored in canonical JSON with an outputs field and connects only through named CustomNodeOutput edges. Migration 502 (CustomNodeOutputsMigration, parameterized so other components can reuse it) rewrites stored deduplication scenarios automatically; a setup replacing DefaultModelMigrations, or a component gaining an additional output after release, needs an equivalent migration - without it the stored scenarios stop validating. An OLDER Nussknacker importing canonical JSON in the new shape silently drops everything downstream of such a node (ScenarioGraph payloads fail loudly instead) - only exchange such scenarios with versions supporting this feature. Every custom node now registers a dead_end meter, counting records that leave through an unwired main output.
Configuration changes
-
!645 OpenAPI enricher:
allowedMethodschanged from a list of strings defaulting to["GET"]to a typed setting that defaults to all methods.- An installation that does not set
allowedMethodsnow exposes every operation the definition declares, not onlyGET. AddallowedMethods: ["GET"]to keep the previous behaviour. - This removes the idempotency guard the old default provided: a definition containing
DELETEorPOSToperations now produces such enrichers by default, and an at-least-once engine can re-invoke them when a scenario is replayed. - Method names are now validated and read case-insensitively. An unknown name (for example
["GTE"]) or an empty list now fails at startup; both were silently accepted before, and both reduced the component to zero services.
- An installation that does not set
-
!413 OpenAPI enricher: the
codesToInterpretAsEmptyconfiguration option was removed.404responses yield an empty (null) result under the defaultError Strategy(Accept 2xx and 404); other status codes previously configured there are no longer interpreted as empty responses. -
#7181 #7620 Added designer configuration: stickyNotesSettings
- maxContentLength - max length of a sticky notes content (characters)
- maxNotesCount - optional, max count of sticky notes inside one scenario/fragment (if not set the amount of sticky notes in scenario is not limited)
- enabled - if set to false stickyNotes feature is disabled, stickyNotes cant be created, they are also not loaded to graph
-
#7534
shouldVerifyBeforeDeployconfiguration entry available for Flink deployment was renamed toscenarioStateVerification.enabled -
#6860 Configuration entry
kafkaEspProperties.forceLatestReadis replaced withkafkaEspProperties.defaultOffsetResetStrategy:- forceLatestRead is missing -> keep defaultOffsetResetStrategy missing or set to "None"
- forceLatestRead: false -> defaultOffsetResetStrategy: "None"
- forceLatestRead: true -> defaultOffsetResetStrategy: "ToLatest"
-
#7568 The
process-jsonbutton inprocessToolbarConfigwas renamed toprocess-export -
#7590 All
akka.*configuration options andAKKA_*and Akka environment variables were replaced with theirpekko.*andPEKKO_*counterparts - it's enough to do a quick search and replace -
#7693 Configuration entry
secondaryEnvironment.remoteConfig.uriis moved tosecondaryEnvironment.uri. -
#8042 When adding multiple OpenAPI components,
ComponentPrefixshould be added to distinguish the components. In the new version of the component, OpenAPIServiceshould be selected. For this reason, the existing scenario may not compile. The automatic migration for this parameter is not easy and has to be done manually or through updates in the DB if you can read the swagger service name. -
#8116 Improved Kafka metadata caching
- Dependencies for
TopicSelectionStrategy(SchemaRegistryClient, andKafkaConfig) should be passed via constructor. kafkaConfig.topicsExistenceValidationConfig.validatorConfigandkafkaConfig.topicsWithoutSchemaFetchTimeoutwere moved to common Kafka admin configurationkafkaConfig.kafkaAdminConfig- see Kafka integration for more details. The properties were moved as follows:topicsExistenceValidationConfig.validatorConfig.autoCreateFlagFetchCacheTtl->kafkaAdminConfig.cacheConfig.autoCreateTopicSettingExpirationTimetopicsExistenceValidationConfig.validatorConfig.topicsFetchCacheTtl->kafkaAdminConfig.cacheConfig.topicsExpirationTimetopicsExistenceValidationConfig.validatorConfig.adminClientTimeout->kafkaAdminConfig.clientTimeouttopicsWithoutSchemaFetchTimeout->kafkaAdminConfig.clientTimeout
- Dependencies for
-
#8523 Kafka components configuration changes:
- Configuration of Kafka components via legacy
modelConfig.kafkaentry is not supported for Flink engine. UsemodelConfig.components.kafka.configinstead. - Configuration of Kafka bootstrap servers via legacy
kafkaAddressis not supported anymore. UsekafkaProperties."bootstrap.servers"instead
- Configuration of Kafka components via legacy
-
#8788
globalParameters.explicitUidInStatefulOperatorsoption was removed - now we always set uid to node id in stateful operators -
#8842!13
avroKryoGenericRecordSchemaIdSerializationAvro optimization option in Kafka source configuration was replaced with a more capableoptimizedGenericRecordSerialization, which can be used with multiple Schema Registry instances:optimizedGenericRecordSerialization.enabled- same as previousavroKryoGenericRecordSchemaIdSerializationboolean flagoptimizedGenericRecordSerialization.schemaRegistryId- Schema Registry instance identifier - each distinct SR environment should get an explicit ID number; defaults to a hash of SR URL, which will make Flink state incompatible if the address changes
-
#9037 Changes around Table-API based Component Providers:
- Component Provider for Table Source and Table Sink - rename from
flinkTableDataSourcetoflinkTableIO - Component Provider for Join and Aggregate components
- renamed from
flinkTableOpstoflinkBatchOps - is no longer loaded by default - no need to disable it for streaming configurations, and for batch configurations,
it can be enabled by
components.flinkBatchOps.disabled: falseconfig undermodelConfig
- renamed from
- Component Provider for Table Source and Table Sink - rename from
-
#9231 OpenAPI component supports new optional cache configuration:
cacheFileLocation- path to persisted cache with last valid OpenAPI definitions.- Discovery refresh now uses stale-on-error fallback. If refresh fails, cached definitions are used from memory and, when configured, from file cache.
- Configuration key
openApiServicesDiscoveryCacheTtlwas renamed todiscoveryCacheTtl.
-
!824 The built-in component groups now have default display names, applied without any
componentsGroupMappingconfiguration. Previously the raw group names were used, so an installation which did not configurecomponentsGroupMappingwill see the toolbox panels renamed accordingly. -
Some built-in components have been moved to a different component group, so they appear in a different toolbox panel (and are reported under a different
componentGroupNameby/api/components) than before:for-each,union,decision-tableandcollectwere moved fromcustom/optionalEndingCustomtobase,raise-errorandloggerwere moved fromservicestomiscellaneous,httpwas moved fromenricherstoservices,delay,previousValue,deduplication,state-transformer,union-memo,aggregate-sliding,aggregate-tumbling,aggregate-session,single-side-join,full-outer-join, the Table APIaggregateandjoin,flink-sql-query,debounceandthrottlewere moved fromcustom/optionalEndingCustomto the newstatefulTransformersgroup.
If you referred to these components' groups - for example in
componentsGroupMapping, or in acomponentGroupoverride incomponentsUiConfig- adjust the configuration to the new groups. -
The
Componentstab filters by the displayed group name, so itsGROUPquery parameter changed accordingly (/components?GROUP=baseis now/components?GROUP=Basic+Components). Bookmarked links using the old names stop matching.
REST API changes
- #7563
ProcessAction.buildInfofield was renamed toProcessAction.modelInfoand is optional now.ProcessActiontype is used inScenarioWithDetails.lastDeployedAction,ScenarioWithDetails.lastStateActionandScenarioWithDetails.lastActionwhich are returned by/processes,/processesDetailsendpoints. It is also used by/components/$id/usagesendpoint - #6860 #7562
- Deploy and cancel http request requires valid json in request body (see
DeployRequestandCancelRequest) instead of plain text, e.g.{"comment": "example text"}. - For KafkaFlinkSource it is possible to provide optional deployment parameter, e.g.
{"comment": "example text", "nodesDeploymentData": {"my_source_node_id": {"offsetResetStrategy": "ToLatest"}}}.
- Deploy and cancel http request requires valid json in request body (see
- #7658
/app/processingtype/reloadendpoint doesn't reload Deployment Managers - #7693 Scenario migration uses
MigrateScenarioRequestDtoV3whereremoteUserNameis removed. To provide username use impersonation mechanism. - #7871
CustomHttpServiceProviderproviding Pekko route was renamed toPekkoCustomHttpServiceProvider. - #7959#9012 Scenario testing API changes:
- Scenario testing API (on path prefix
/scenarioTesting) is refactored, with modified endpoint paths and request/response format - endpoints moved from
/processManagementAPI to/scenarioTestingAPI/test(test with form)/generateAndTest(test with generated data) and merged into a single endpoints/performTest/testto/performTest/testCaseto/performTestCase* introducednew representation of test results, grouped per transition between nodes (toggleable in on API request level)
- Scenario testing API (on path prefix
- #8997 Node IDs were changed to technical UUIDs and separated from user-facing node names:
- Existing scenarios are automatically migrated: previous human-readable node id is moved to node
name, and a new UUID is generated as nodeid. - In scenario JSON and HTTP DTOs, node
idis now technical and stable (UUID), while nodenameis user-editable and should be used for UI-facing text. ValidationResultresponse containsnodeNamesmap (nodeId -> nodeName) to allow clients to render readable node labels.KafkaExceptionInfopayload now containsnodeName, and existingnodeIdfield now contains technical UUID values (not user labels).- Links/query params that point to nodes by id (e.g. visualization URLs with
nodeId=...) now require technical UUIDs. Old links based on former human-readable ids stop matching nodes. - Join nodes'
branchParameters[].branchIdin the scenario graph (designer/REST DTO) now also uses the predecessor node UUID, consistent with edges (edge.from); the persistedCanonicalProcesskeeps the node name there, so no scenario migration is required.
- Existing scenarios are automatically migrated: previous human-readable node id is moved to node
- !625 New
EdgeType.CustomNodeOutput(name: String)discriminator (JSON"type": "CustomNodeOutput"): every outgoing edge of a node whose component declares additional outputs is persisted with it, andUINodeEdgeslists the declared outputs (main first) for such components. Clients decodingEdgeTypeexhaustively must handle the new case; an unrecognized discriminator in aScenarioGraphpayload fails decoding loudly. - !878 The whole
/api/deploymentsAPI was removed and now returns 404. Use the scenario management endpoints instead
Code API changes
- !680
ModelClassLoadernow exposesclassPath: ModelClassPath, which keeps, for every configuredmodelConfig.classPathentry, the URL it resolved to and the URLs it expanded to;urlsis unchanged and still returns the flattened list. ConsequentlyFlinkModelJarProvidertakes aModelClassPathand anOption[ModelArtifactConfig]instead ofList[URL]- useModelClassPath.fromUrls(urls)to keep the previous behaviour, or passmodelClassLoader.classPathto be able to skip cluster-provided entries, as configured viadeploymentConfig.modelArtifact(see the Changelog).FlinkClient.runProgramtakes an additionalflinkConfiguration: Map[String, String]parameter - passMap.emptyto keep the previous behaviour. The same two values are now constructor parameters ofFlinkDeploymentManagerandRemoteFlinkScenarioJobRunner, and arguments ofFlinkScheduledExecutionPerformer.create- passnew FlinkModelJarProvider(modelDataProvider.modelClassLoader.classPath)andMap.emptyto keep the previous behaviour. - !689 Category is now typed as
CategoryId(pl.touk.nussknacker.engine.api.CategoryId, wraps the idString) instead of a rawString, inLoggedUser/CommonUser(security),WithCategories/ProcessingTypeConfig/ProcessMigration.migrateProcess(extensions-api),ScenarioService(custom-http-service-api), andScenarioWithDetailsForMigrations(restmodel). Wrap withCategoryId(...)/ unwrap with.valueat call sites. request-response-runtime: the routes serving one scenario were reorganised for the interaction feature, which is source-breaking for code building request-response routes itself (ScenarioDeploymentExtensionimplementations and similar).ScenarioRouteHelpers.resumeRoutetakes an extracontinuationTtlargument and now answers an unknowncontinuationIditself instead of rejecting, so the separateScenarioRouteHelpers.unknownContinuationIdRouteis gone. OnScenarioRoute,resumeRoutes,unknownContinuationIdRoute,routeWithoutUnknownContinuationIdFallback,drainingRouteandcombinedDrainingRoutewere replaced bycombinedRoute(a whole scenario version),invocationAndDefinitionRoutes(everything but/resume) andScenarioRoute.resumeRoute(one/resumeroute shared by every interpreter mounted under a scenario slug, across all its live versions - a single route is required, because the request entity can only be read once).ScenarioRouteno longer takes ascenarioVersionId: the resume endpoint is not version-scoped.request-response-components-api: newContinuationNotResumableException, thrown when a/resumereaches the interpreter but the continuation has been consumed or has expired in the meantime; the runtime answers it with400rather than500. Code matching on the previousIllegalArgumentExceptionfrom that path needs updating.scenario-api:CustomNodeandEnrichergained a new optional field,mockExpression: Option[Expression] = None, used to inline a fixed value in place of the node's real (side-effecting) evaluation - currently used to mock aninteractionnode's resumed input during ad-hoc scenario testing. The field defaults toNone, so existing scenario JSON and code constructing these case classes without it keep working unchanged.- !625 Named outputs for custom components:
CustomStreamTransformergaineddef outputs: NonEmptyList[ComponentOutput](head = main output; the default keeps subclasses source-compatible), andComponentOutputwraps aStringrefined asNonEmpty And Trimmed(ComponentOutput.Name), so a name may be neither empty nor padded with whitespace.CustomComponentSpecificDatagained a third field (outputs), so a positional pattern match needs an extra_. SealedCanonicalNode,SubsequentNodeandEdgeTypeeach gained a case for the multi-output shape (CustomNodeWithOutputs/CustomNodeOutput), so exhaustive matches - e.g. a customProcessMigration- must be extended. New save-blockingProcessCompilationErrorcases:UnknownCustomNodeOutput,MissingCustomNodeOutputName,UnsupportedEdgeNextToCustomNodeOutputs,DuplicateCustomNodeOutputNamesandMultipleOutputsToSameJoin; additionally a node other thansplitmay now have at most one unnamed outgoing edge (previously such an API-submitted graph saved and got spliced into one chain). It is now rejected withNonUniqueEdgeType("main output", ...).splittedgraph.part.CustomNodePartwas reshaped into a sealed trait with one case per shape:MultiOutputCustomNodePart(node, outputs: NonEmptyList[SplittedOutput])for a node connected through named edges - every wired continuation, the main one included, lives inoutputs(eachSplittedOutputcarries its ownnameand thenextParts/endsof its output; an output the scenario leaves unwired has no entry) andnodeis a bareEndingNode- andSingleOutputCustomNodePart(node, nextParts, ends)for the released single-output form, where the continuation stays embedded innode. The multi-output case computes the inheritednextParts/endsmembers as the concatenation of every output's, so generic consumers still see every downstream part, but construction and pattern matches against the old single class break. Its counterpartcompiledgraph.part.CustomNodePartfolds every output into one type -CustomNodePart(transformer, contextBefore, validationContext, outputs: NonEmptyList[CompiledOutput])- where aCompiledOutputcarries the output's identity (output: ComponentOutput) plus its ownnode,nextPartsandends. The list is built from the component declaration, so the head is always the main output (with aDeadEndstanding in when the scenario leaves it unwired) and the connected additional outputs follow in declaration order.nodeis no longer a field of the part: it isoutputs.head.node, so it also leaves the extractor.nextParts/endsconcatenate every output's, so positional construction and pattern matches break there too (scenario-compiler/.../splittedgraph/part.scala,scenario-compiler/.../compiledgraph/part.scala).FlinkCustomStreamTransformationis unchanged for a component with only the main output:transformstill returns a singleDataStream[ValueWithContext[AnyRef]]and theFlinkCustomStreamTransformation(...)factories still take the same lambdas, so no such component needs migrating. A component with additional outputs implements the new, unrelatedFlinkMultiOutputStreamTransformation, whosetransformreturnsNonEmptyList[(ComponentOutput, DataStream[ValueWithContext[AnyRef]])]instead: the returned list restates the component'soutputsdeclaration with a stream attached to each entry, keyed by the output it belongs to. Job registration looks the streams up by key, so their order does not matter. The main output always needs exactly one stream, whether or not the scenario wires it; an additional output needs one only when the scenario connects it, and the streams of the unconnected ones are never read. Omitting a stream that is needed, or returning two under the same key, fails job registration loudly. Its lambda form isFlinkMultiOutputStreamTransformation { (start, ctx) => ... }. AFlinkCustomStreamTransformationreturns no key at all: registration wires its single stream to the main output whatever the component named it, so renaming the main output alone is no reason to reach for the multi-output trait. Registration fails there rather than letting an output the scenario wired silently emit nothing. Additional outputs are usually routed as Flink side outputs:FlinkCustomNodeContext.createOutputTag(output, typeInfo)gives a ready tag, the component emits under it and reads the stream back withgetSideOutputon the emitting operator.typeInfodescribes what that output emits and becomes the type of the streamgetSideOutputreturns, so pass the one the emitting operator uses for its own output, normally fromFlinkCustomNodeContext.valueWithContextInfo; nothing verifies it, becauseOutputTagcompares by name alone. That is one pass over the stream with each element going to exactly one output, and taking the tag from the same place on both ends keeps them identical. Nothing forces that shape though - any stream will do, so an output may have its own chain of operators. Every output has the same shape: theContextcarried must be consistent with the node's declared output context (for typical components, the unchanged input context), and the accompanying value becomes the node's output variable on that output. A component with nothing to report on an output emitsValueWithContext(null, ctx), which means the output variable is in scope downstream of that output holdingnullrather than being absent.- Joins (
canHaveManyInputs = true) cannot declare additional outputs - the combination is rejected when the component definition is loaded; duplicate declared output names are rejected the same way. Like other component definition errors, the rejection is anIllegalArgumentExceptionthrown at model load, so one invalid declaration prevents the whole processing type from starting. - A component declaring any additional outputs (a non-default
outputstail) has to return an implementation carrying the newcomponent.SupportsMultipleOutputsmarker, which on Flink onlyFlinkMultiOutputStreamTransformationcarries. If the returned implementation does not carry it - another runtime's, or a FlinkFlinkCustomStreamTransformation, which structurally cannot route more than one output - a scenario that connects one of the declared additional outputs fails compilation withCustomNodeError, so the designer reports it on save instead of letting the deployment fail. Only connected additional outputs are checked: a scenario that wires none of them - even one that wires only the main output - keeps compiling, because an unconnected output costs it nothing at runtime. This is also what rejects such a scenario on Lite: additional outputs target the Flink streaming runtime for now, so no lite implementation carries the marker. Adding them to another engine means marking that runtime's own transformation type.
- !405
schemed-kafka-components-utils: the parameter handling ofUniversalKafkaSinkFactorywas extracted to the newUniversalKafkaWriterFactorytrait (shared with the request-responsekafkaservice). Behavior is unchanged.KafkaUniversalComponentTransformerstays an abstract class (subclasses are unaffected), but its shared logic now lives in theKafkaUniversalComponentTransformerTraitit extends. The only source-breaking change:TransformationStatemoved from theUniversalKafkaSinkFactorycompanion object to theUniversalKafkaWriterFactorycompanion object. - !417 Request-Response: sinks can declare the HTTP status code and encoding of the scenario response.
- The
outputSchemascenario property can now be a map from HTTP status code to JSON Schema with a requireddefaultentry (e.g.{"default": {...}, "404": {...}}). The previous single-JSON-Schema format is still read as thedefaultschema, so existing scenarios keep working without any migration. - New request-response
components-apitraits:SinkWithHttpStatusCode(its code typed as the newHttpStatusCodeenum) andSinkWithResponseEncoder; the built-inresponsesink implements both, picking the encoder for its declared code and falling back to thedefaultschema.ResponseRequestSinkImplFactory.createSinktakes an extrastatusCode: HttpStatusCode. - Lite
components-api:ScenarioInterpreterhas a new membersinks: Map[NodeId, Sink]that custom implementations must provide. - In the request-response runtime,
invokeToOutputnow returnsRequestResponseOutput(results, statusCode, responseEncoder)instead ofList[Any],getSchemaOutputPropertyreturnsOutputSchemaMapinstead ofJson, andRequestResponseHttpHandler.invokereturnsScenarioResponse(body, statusCode)instead ofJson.
- The
- #9399
pl.touk.nussknacker.ui.process.migrate.RemoteEnvironmentchanges, used to support comparing scenario versions against a remote (secondary) environment:- One new abstract method,
versionsWithDifferences. Any external implementation of this trait must implement it. versionsWithDifferencesis backed by a new endpoint,POST /processes/{scenarioName}/versions-with-differences, which takes a scenario graph in the request body and answers with the subset of that environment's own versions that differ from it. The comparison deliberately runs on the environment that already stores those versions, so one graph is sent and a summary comes back, rather than full scenario graphs being pulled across the network to be compared locally. One request answers for as many of the scenario's most recent versions as thelimitquery parameter asks for (default 50, maximum 500) - the answering environment applies that limit before loading any graph, so it never walks its whole history, and reportsoldestComparedVersionIdwhen it stopped short. Version comments are returned separately, inversionComments, covering every version rather than only the compared ones - the answering environment reads them from its own activity list, so no second request is made for them. Comments recorded against scheduled or ad-hoc executions, and against deployments that failed, do not describe a version and are not included. The endpoint requires theReadpermission on the scenario. Comparing scenario versions against a remote environment therefore requires that environment to run Nussknacker 1.19.0 or newer; against an older one the designer reports that the differences could not be determined.processVersionsnow returnsFuture[RemoteScenarioVersions]instead ofFuture[List[ScenarioVersion]]. The new wrapper carries aremoteUnavailableflag, so implementations report "the remote environment could not be reached" without failing theFuture- previously indistinguishable from "the remote has no such scenario". Implementations returnRemoteScenarioVersions(versions, remoteUnavailable = false)for a successful fetch.GET /remoteEnvironment/{scenarioName}/versionsnow responds502 Bad Gatewaywhen the remote environment is unreachable or rejects our credentials, instead of returning an empty list. A remote environment that simply does not have the scenario yet still returns an empty list.GET /remoteEnvironment/{scenarioName}/versionsnow also requires theReadpermission on the scenario and responds403 Forbiddenwithout it. Previously the endpoint had no permission check, so any authenticated user could read the remote environment's version history for any scenario; a client that relied on getting an empty list for an inaccessible scenario has to handle403now.- Comparing against a remote environment now fetches the remote scenario graph without validation and dictionary resolution, so both sides of the comparison are the raw stored graph. Scenarios using dictionaries previously reported differences on every node whose parameters referenced a dictionary.
GET /processes/{scenarioName}accepts a new optionalskipScenarioGraphquery parameter (defaultfalse). With it the response omitsscenarioGraph, which is whatprocessVersionsuses when it needs only the version history. The parameter is additive - a client that does not send it, or an environment that does not recognise it, is unaffected.
- One new abstract method,
- !338 Flink
components-api: keyed end-of-input flushing and restore re-pacing operators (packagepl.touk.nussknacker.engine.flink.api.operator).EndInputFlushableFunction[OUT]is nowKeyedFlushFunction[K, OUT], and its flush callback gains the current key and a shorter name:flushPendingEventsForCurrentKey(output)→flushForCurrentKey(key: K, output). Implementations (aKeyedProcessFunctionwired throughOneInputFlushingKeyedOperator) must add theKtype parameter and update the method signature.- New restore-able operators:
KeyedRestoreFunction[K, OUT]plusRestorableKeyedOperator[K, IN, OUT](restore-only) andRestorableOneInputFlushingKeyedOperator[K, IN, OUT](end-of-input flushing + restore). AKeyedProcessFunctionmixes inKeyedRestoreFunctionto re-pace its per-key buffered events once after a state restore viarestoreForCurrentKey(key, timerService); implementations that need no rescheduling (e.g. event time) make it a no-op.
- !155
TransformStateTransformerwas rewritten as a dynamic component (and registered as the newstate-transformercomponent):TransformStateFunctionis nowprivate[transformer]- it is an implementation detail and should not be referenced directly- the
#previousvariable was replaced by#current, thestateTimeoutSeconds: Longparameter was replaced byttl: Duration, and a new mandatoryinitialValueparameter was added
- !247 Script Processor added
Expression.Language.Pythonas a newExpression.Language.ScriptLanguage. Code that pattern-matches exhaustively onExpression.LanguageorScriptLanguageshould handle this new case or use the existing_: ScriptLanguagebranch. - !242 Built-in parameter validators: runtime validation,
@NotNull/@NotEmptysupport and naming cleanup.- Affected validators:
NotNullValidator,NotBlankValidator,RegExpValidator,MinimalNumberValidator,MaximalNumberValidator, and the newNotEmptyCollectionValidator. Each now also implementsRuntimeValidator; when attached to a parameter, the evaluated value is validated at runtime after expression evaluation, and a violation throwsParameterRuntimeValidationException(aNonTransientException). Compile-time behavior is unchanged. - Behavior change: validators auto-attached via annotations (
@NotBlanktoNotBlankValidator,@MintoMinimalNumberValidator,@MaxtoMaximalNumberValidator) now also reject invalid values at runtime. A scenario that previously passed a dynamic blank or out-of-range value through such a parameter at runtime will now fail withParameterRuntimeValidationException. - New annotation mappings:
@NotNullnow attachesNotNullValidatorand@NotEmptyattachesNotEmptyCollectionValidator. Both annotations were previously ignored, so a parameter carrying them gains new validation at both compile time and runtime, and a scenario that compiled before may now fail compilation or at runtime.@NotNullis attached in addition to theMandatoryExpressionValidatorthat non-optional parameters already receive (the two checks are intentionally distinct).NotEmptyCollectionValidatoronly checksjava.util.Collectionandjava.util.Map(by design), so@NotEmptyon aStringor array is not validated; use@NotBlankfor string parameters. NotBlankValidator,RegExpValidator, andNotEmptyCollectionValidatorpassnullthrough to allow validator chaining; combine them withNotNullValidatorto also rejectnull.- Other built-in validators (
MandatoryExpressionValidator,JsonExpressionValidator,FixedValuesExpressionValidator,LiteralIntegerExpressionValidator,MultiSelectFixedValuesExpressionValidator) remain compile-time only. - Built-in validators were renamed to reflect when they run:
*ExpressionValidatorruns at compile time on the expression,*ValueValidatorat runtime on the evaluated value,*Validatorat both. Renames (Code API change):MandatoryParameterValidator→MandatoryExpressionValidator,NotNullParameterValidator→NotNullValidator,NotBlankParameterValidator→NotBlankValidator,NotEmptyCollectionParameterValidator→NotEmptyCollectionValidator,RegExpParameterValidator→RegExpValidator,FixedValuesValidator→FixedValuesExpressionValidator,LiteralIntegerValidator→LiteralIntegerExpressionValidator,JsonValidator→JsonExpressionValidator,MultiSelectFixedValuesValidator→MultiSelectFixedValuesExpressionValidator.MinimalNumberValidator,MaximalNumberValidator, andCompileTimeEvaluableValueValidatorkeep their names. The JSON serialization format (the"type"field) is unchanged, so saved scenarios and configurations are not affected. - New
CompileTimeAndRuntimeValidatortrait (extendsCompileTimeParameterValidator with RuntimeParameterValidator) is the base for validators that run at both stages: an implementation providesmessage,description,validate, andcompileTimeError, while bothisValidmethods and a defaultruntimeError(which usesmessage) are inherited. All built-in dual validators extend it.
- Affected validators:
- Runtime parameter validation:
Validator,ParameterValidator, andCustomParameterValidatortrait hierarchies refactored.Validatoris now a sealed trait with noisValidmethod. Two new sub-traits carry the validation logic:CompileTimeValidator— the existingisValid(paramName, expression, value, label)(nodeId)returningValidated[PartSubGraphCompilationError, Unit]. All built-in validators implement this.RuntimeValidator— new;isValid(paramName, expression, value: Any)(nodeId)returningValidated[ParameterRuntimeValidationError, Unit]. Called after expression evaluation at runtime.
CompileTimeParameterValidator extends ParameterValidator with CompileTimeValidatorandRuntimeParameterValidator extends ParameterValidator with RuntimeValidatorare the new intermediate traits.CustomParameterValidatoris now a sealed trait with onlydef name: String. It no longer extendsValidator. Replace usages of the oldCustomParameterValidator(which extendedValidator) with:CustomCompileTimeParameterValidator extends CustomParameterValidator with CompileTimeValidator— compile-time custom validation.CustomRuntimeParameterValidator extends CustomParameterValidator with RuntimeValidator— runtime custom validation.- A class may extend both if it needs to validate at both stages.
CustomParameterValidatorDelegateis renamed toCustomParameterValidatorByNameLoader. JSON serialization format is unchanged — it still encodes/decodes as"type": "CustomParameterValidatorDelegate"with a"name"key.CustomParameterValidatorLoader.resolvednow returnsParameterValidator with WithUnderlyingCustomParameterValidatorinstead ofCustomParameterValidator. Code that previously assignedresolvedto aCustomParameterValidatorvariable must be updated.- New
CustomParameterValidatorByClassLoaderloads aCustomParameterValidatorby fully-qualified class name (used by the@CustomValidatorannotation). It serializes as"type": "CustomParameterValidatorDelegate"with a"className"key. - New
@CustomValidator(classOf[MyValidator])Java annotation inpl.touk.nussknacker.engine.api.validationattaches aCustomParameterValidatorimplementation to a parameter by class (alternative to the existing name-basedCustomParameterValidatorByNameLoader). ParameterValidatorJSON codec rewritten manually (was@ConfiguredJsonCodec).ScenarioPropertyConfigalso receives an explicitDecoderin place of@JsonCodec.
- !316 Parameter labels are now represented by the
ParameterLabelvalue object (pl.touk.nussknacker.engine.api.parameter.ParameterLabel) instead of a rawString.Parameter.labelOptis nowOption[ParameterLabel]instead ofOption[String]. Wrap raw strings withParameterLabel(...)at construction sites.Parameter.labelitself is removed, in favor ofparamName.displayName.- There is no serialization/wire change - the designer-facing
UIParameter.labelstays aString.
- !772 Compilation errors and the validation APIs a component calls
now carry
ParameterNameWithLabel(namepluslabelOpt, rendered bydisplayName) instead ofParameterName, so a message can show the label the user sees. Pass a label wherever the component knows one -parameter.paramNameWithLabelif aParameteris at hand.- Fields and parameters holding it were renamed
paramName->paramNameWithLabel. Named arguments and member reads must be updated; positional patterns still work. ValidationContext.withVariableOverridenwas renamed towithVariableOverridden.ParameterNameWithLabel.apply(String)is gone - writeParameterNameWithLabel(ParameterName("myParam")).withBranchIdsuffixes the name only - compareparamNameWithLabel.name, not a pre-builtParameterName("key for branch b1").- Validation message texts changed: identifiers are wrapped in single quotes, and the plain-text node endpoints name the parameter. Code matching on exact message text must be updated.
ParameterRuntimeValidationExceptiongained aparamLabel: Option[ParameterLabel]field next toparamName, so code constructing it positionally must be updated. It can now be built from the whole identity withParameterRuntimeValidationException(paramNameWithLabel, input, message).ProcessCompilationError.UnknownPropertywas removed. It had no producer left after #7757 dropped the unknown scenario property validation. A test source parameter with no value in the submitted test record is now reported asMissingParameters. Code matching onUnknownPropertymust be updated.
- Fields and parameters holding it were renamed
- #8719 Feature: Add possibility to pass trace id to Context
- added optional
traceIdfield atContext, default None - Fro now
RequestResponseSourcetransformsRecord[T]instead T as a record
- added optional
- #8723 Change: Passing
Contextinstead ofContextIdat EagerServiceWithStaticParametersAndReturnType.invoke - #7165
pl.touk.nussknacker.engine.api.deployment.DeploymentManager:- new command
DMPerformSingleExecutionCommand, which must be handled inDeploymentManager.processCommandmethod (handle it the same asDMCustomActionCommandwith actionName=run now) - added new arguments to
def resolveandgetProcessStatemethods (latestVersionId: VersionId,deployedVersionId: Option[VersionId]), which will be provided by Nu when invoking this method
- new command
pl.touk.nussknacker.engine.api.deployment.ProcessStateDefinitionManager:- added new arguments to
def processStatemethod (latestVersionId: VersionId,deployedVersionId: Option[VersionId]) - added new methods with default implementations:
def visibleActions: List[ScenarioActionName]- allows to specify, which actions are applicable to scenario (and consequently should be visible in Designer), by default all previously available actionsdef actionTooltips(processStatus: ProcessStatus): Map[ScenarioActionName, String]- allows to define custom tooltips for actions, if not defined the default is still used
- modified method:
def statusActions(processStatus: ProcessStatus): List[ScenarioActionName]- changed argument, to include information about latest and deployed versions
- added new arguments to
- #7379 Removed CustomAction mechanism. If there were any custom actions defined in some custom DeploymentManager implementation, they should be modified to use the predefined set of actions or otherwise replaced by custom links and handled outside Nussknacker.
- #7368 #7502 Renamed
PeriodicSourceFactorytoEventGeneratorSourceFactory - #7364 The DeploymentManager must implement
def schedulingSupport: SchedulingSupport. If support not added, thenNoSchedulingSupportshould be used. - #7511 Changes around flink-based scenario testing. As an entry point to all migration steps, assume that
FlinkMiniClusterWithServicesis a newFlinkMiniClusterHolder- From perspective of testkit (
TestScenarioRunner.flinkBased) module usageflink-testsmodule doesn't depend onflink-test-utilsmodule. To createFlinkMiniClusterWithServicesfollow steps below. Example migration process is also available in PR with the related change.FlinkSpecinheritance should be removed from test class- Test class should extend
BeforeAndAfterAll FlinkMiniClusterWithServicesshould be created usingval flinkMiniClusterWithServices = FlinkMiniClusterFactory.createUnitTestsMiniClusterWithServices()FlinkMiniClusterWithServicesshould be closed inafterAllblock
- From perspective of
flink-test-utilsmodule usage follow steps below. Example migration process is also available in PR with the related change. Caution: this module is deprecated; to avoid further migrations issues, tests should be rewritten to testkit stack- Instead of using
FlinkSpec.flinkMiniCluster.createExecutionEnvironmentmethod, should be usedFlinkSpec.flinkMiniCluster.withDetachedStreamExecutionEnvironmentwhich properly closes created environment MiniClusterExecutionEnvironmentclass was removed, plainStreamExecutionEnvironmentis returned instead- To access methods such as
withJobRunning, importScalatestMiniClusterJobStatusCheckingOps._and then invoke these methods onflinkMiniCluster - Method
withJobRunningwas renamed towithRunningJoband it doesn't invokeStreamExecutionEnvironment.execute. It should be called before this method - Method
executeAndWaitForFinishedwas renamed towaitForJobIsFinishedand it doesn't invokeStreamExecutionEnvironment.execute. It should be called before this method; also, this method cancel job if check ended up with error now - Method
assertJobNotFailingwas renamed tocheckJobIsNotFailing - Some methods are not available in
ScalatestMiniClusterJobStatusCheckingOps:executeAndWaitForStart,waitForStart,stopJob- should be usedwithRunningJob/waitForJobIsFinishedorFlinkMiniClusterWithServices.miniClustermethods directly instead- Other methods were considered too much low-level and were removed
- To access methods such as
- Instead of using
ResultsCollectingListenerHolder.registerListenerorResultsCollectingListenerHolder.registerTestEngineListenershould be usedwithListener/withTestEngineListenermethods which properly cleanup allocated resources.
- Instead of using
- From perspective of testkit (
- #7540
FlinkStreamingDeploymentManagerProviderwas renamed toFlinkDeploymentManagerProvider,FlinkStreamingRestManagerandFlinkRestManagerabstraction layers were removed - onlyFlinkDeploymentManagerexists - #7563
ProcessConfigCreator.buildInfoandNkGlobalParameters.buildInfowere renamed tomodelInfoAlso, they return aModelInfovalue class now. To create it fromMap, useModelInfo.fromMap. To access underlying map, useModelInfo.parameters. - #7566 Scenario status and deployment statuses are decoupled now
- Changes in
DeploymentManagerinterfaceDeploymentManagerhas onlygetScenarioDeploymentsStatusesmethod (previousgetProcessStatesreturningList[StatusDetails]).- Method
DeploymentManager.resolveshould be removed - this work is done by Designer itself DeploymentManagerInconsistentStateHandlerMixInmixin should be also removedstateQueryForAllScenariosSupportwas renamed todeploymentsStatusesQueryForAllScenariosSupport
- Other changes:
StatusDetailswas renamed toDeploymentStatusDetails- Fields:
externalDeploymentId,externalDeploymentId,attributes,attributeswere removed fromStatusDetails
- Changes in
- #7658
DeploymentManageris not reloaded during processing type reloadDeploymentManagerProvider.createDeploymentManager()takesBaseModelDataProviderinstead ofBaseModelData- To access
modelClassLoaderuseBaseModelDataProvider.modelClassLoader - To access other fields from
ModelData, useBaseModelDataProvider.getCurrentModelData() - To create
BaseModelDataProviderfromModelDatauseBaseModelData.toModelDataProviderextension method
- To access
- #7598 Classes from
pl.touk.nussknacker.engine.sttppackage were moved topl.touk.nussknacker.http.backend - #7586 Renamed ComponentUseCase to ComponentUseContext.
- Moved NodeDeploymentData from FlinkCustomNodeContext to ComponentUseContext.LiveRuntime.
- Introduced ComponentUseContextProvider in ScenarioCompiler, which retains ComponentUseCase functionality but is now intended for internal use only.
- #7618
NonTransientExceptionis a normal class instead of case class. We recommend to create explicit classes extending this class, but still it can be created directly but withnew NonTransientException(...) - #7590 Akka and Akka HTTP were replaced with Apache Pekko 1.0.3 / Apache Pekko HTTP 1.0.1.
These versions are API-compatible with previously used Akka versions, so after updating dependencies it should be enough
to replace all
akka.*imports withorg.apache.pekko.*and change theakkaprefix in configuration entries topekko. More details can be found in: - #7632 Simplified parameter editors API.
- Removed the single
editorfrom the UIParameter and now only theeditorsproperty is available. - Replaced the
editorparameter witheditorsin the engine APIParameter. - Similarly,
ParameterConfigin engine API now accepts aneditorslist instead of a single editor. - Removed a
DualEditorfrom the components API.- Renamed a
SimpleEditorto theEditorin components API. - For now on, you can add multiple editors on a single param. The first editor annotation is treated as a default editor.
- Renamed a
- Removed the single
- #7711 #7984
TypingResultAPI changes:TypedNull.wihoutValuereturnsUnknowntype instead ofTypedNullcanBeConvertedTorenamed tocanBeLooselyAssignedTocanBeStrictlyConvertedTorenamed tocanBeStrictlyAssignedTo
- #7768
ModelData.withThisAsContextClassLoaderwas renamed towithModelClassloaderAsContextClassLoader- New,
DeploymentManager.scenarioCompilationDependenciesResourcemethod was added. For flink-based DMs it should be implemented asminiClusterWithServices.createDetachedStreamExecutionEnvironment[SyncIO].map(new FlinkScenarioCompilationDependencies(_))
- #7824 Introduced Json display for
Unknowntype.Unknownis a case class now and it hasDisplayStrategyfield. It affects how the type is displayed.- There is
Unknownobject which extends the case class withDefaultDisplayStrategyfor compatibility. - When introducing new pattern matches regarding types
Unknown(_)should be used so all display strategies are targeted.
- #8054
ProcessObjectDependenciesclass was replaced byModelConfig - #8256 The support for kafka source generating custom classes (
KafkaSourceFactory) was removed We recommend a migration to more generic approach:UniversalKafkaSourceFactory - #8308
ToJsonEncoderrefactor:ToJsonEncoderwas moved topl.touk.nussknacker.engine.api.json.encoderspackageToJsonEncoderis a sealed trait, if you want to extend it, use eitherStrictToJsonEncoder(oldfailOnUnknown = true) orLooseToJsonEncoder(oldfailOnUnknown = false)highPrioritybecome a method instead of parameterToJsonEncoder.encodemethod now returnsValidatedand is available only forStrictToJsonEncoderToJsonEncoder.encodeUnsafemethod behave as the previousToJsonEncoder.encode(errors are thrown as Exceptions)
- #8523 Kafka components configuration changes:
KafkaConfigwas renamed toKafkaComponentsConfigKafkaComponentsConfig.kafkaPropertiesis mandatory nowKafkaComponentsConfig.kafkaAddresswas removed
- #8576
NodeIdvalue class become used more frequently in the API:NodeComponentInfo,ContextId,ProcessCompilationError,ProcessListenerandFlinkCustomNodeContext - #8997 Node identity semantics changed in API modules:
NodeIdshould be treated as internal technical identity (UUID) and not shown to end users as a readable label.NodeNameis now the user-facing label; for user-visible errors/logs/messages useNodeName, optionally withNodeIdonly as technical details.- If your custom code (including integrations based on
*-apimodules) assumednodeId == displayed node name, it must be updated to use both fields explicitly. - In places where you serialize/deserialize scenario-related HTTP payloads, ensure mappings preserve both
idandnamefields.
- #8632
DynamicComponent's[T]generic parameter was replaced withImplementationtype We recommend to not invokeDynamicComponent.implemenation()method directly. To check how component behave during compilation, useTestNodeCompilerinstead. Read Testing for more info. - #8781
WithExceptionHandlerhelper trait was removed because it made it easy to unintentionally hide original class'closemethod - #8778 #8777 Legacy Flink 1.x APIs removal
- Custom, Nussknacker's
TimestampWatermarkHandlerabstraction was replaced by Flink'sWatermarkStrategyFlinkSourceTestSupport.timestampAssignerForTestwas renamed towatermarkStrategyForTestCustomizableTimestampWatermarkHandlerSourcewas renamed toCustomizableWatermarkStrategySource[Raw]StandardTimestampWatermarkHandlerwas renamed toWatermarkStrategyUtils- Nussknacker's
SimpleSerializableTimestampAssignerwas removed - use Flink'sSimpleSerializableTimestampAssignerinstead
AssignerWithPunctuatedWatermarks/AssignerWithPeriodicWatermarksinterfaces were removed from Nussknacker APIBlockingQueueSourcenow takesextractTimestampFun: T => Long, maxOutOfOrderness: Durationinstead ofAssignerWithPunctuatedWatermarks[T]EmitWatermarkAfterEachElementCollectionSourcewas removed. UseCollectionSourcecombined withWatermarkStrategyUtils.afterEachEventBoundedOutOfOrdernessPunctuatedExtractorwere removed - useWatermarkStrategyUtils.afterEachEventinsteadBoundedOutOfOrderPreviousElementAssignerwas removed - use customWatermarkStrategyinstead
BasicFlinkSink.toFlinkFunctionwas replaced bytoFlinkSink; the new method returnssink2.Sinkinstead ofSinkFunction
- Custom, Nussknacker's
- #8788
ExplicitUidInOperatorsSupporttrait was removed. UsesetUidAndNameToNodeIdextension method available inDataStreamImplicitsinstead - #8786
StandardFlinkSource,BaseFlinkSourceandCustomizableWatermarkStrategySourcetraits were removed. UsesetUidAndNameToNodeId,assignTimestampsAndWatermarksand context initialization (FlinkContextInitializingFunction) directly - #9327
FileSystemBindand associated bind mounting helpers in Docker tests were removed. UseContainerVolumeinstead. - Removed
pl.touk.nussknacker.engine.process.registrar.StreamExecutionEnvPreparer.sideOutputGetter. CustomStreamExecutionEnvPreparerimplementations should remove this method.
Other changes
- !860 Kafka client library was updated to 4.2.1, the lowest supported version of Kafka broker is 2.5.
- !863
#AGG.listaggregate now returns the aggregated elements oldest first - !485 Behavior change: duration parameters of several base components are now validated at scenario compile time.
A scenario that previously compiled becomes invalid when a constant (compile-time evaluable) duration violates the new constraint - fix the reported parameter value:
- must be positive (> 0):
deduplicationttl,state-transformerttl,union-memostateTimeout,full-outer-joinwindowLength,aggregate-sliding/aggregate-tumblingwindowLength,aggregate-sessionsessionTimeout, SQL enrichers (query/lookup)Cache TTL(only when set),kafka/tableIdleness(only when set) - must not be negative (>= 0):
delaydelay(constant expressions only; a non-positive value computed per event still releases the event immediately),single-side-joinwindowLengthBeforeEvent/windowLengthAfterEvent,event-generatorschedule(zero still means the maximum generation rate),kafka/table/event-generatorMax out-of-orderness
- must be positive (> 0):
- !248 The
delaycomponent was reworked:- The
keyparameter was renamed tokeyBy. Existing scenarios using thedelaycomponent must update this parameter (renamekeytokeyBy), either manually or via a scenario/DB migration. - A new advanced parameter
timeMode(EventTime/ProcessingTime) was added. Its default can be configured via the optionalcomponents.base.delay.timeModesetting; when not configured it defaults toProcessingTime(keyByanddelayhave fixed defaults""and100ms). - Behavior change: the previous default was event time. Delay nodes that do not set
timeModenow run in processing time. To keep the previous behavior, either set the node'stimeModetoEventTime, or configurecomponents.base.delay.timeMode: "EventTime".
- The
- #7116 Improve missing Flink Kafka Source / Sink TypeInformation
- We lost support for old ConsumerRecord constructor supported by Flink 1.14 / 1.15
- If you used Kafka source/sink components in your scenarios then state of these scenarios won't be restored
- #8997 Operational impact of random/stable technical node IDs:
- During first migration of existing scenarios, node ids change to UUIDs, so external tools comparing scenario JSON by node ids can observe large one-time diffs.
- Migration
NodeIdToUuidMigrationmust be applied in model migration list, so legacy scenarios are migrated to UUID-based node ids. - Metrics dimensions based on
nodeIdchanged to UUID values. If dashboards/alerts used former human-readable ids, they require updates. Where available, prefernodeNamemetric tag for human-readable presentation. - Kafka consumer groups using naming strategy containing
nodeId(e.g.processId-nodeId) will change identifiers after migration. This can require offsets migration / planned cutover. - Flink operator UIDs are now based on technical node IDs. For scenarios migrated from old ids, savepoints/checkpoints created before migration can become incompatible.
- #7257 #7259
components-apimodule doesn't depend onasync-http-client-backend-future,http-utilsmodule is delivered byflink-executorandlite-runtimemodules. If your component had compile-time dependency tohttp-utils, it should be replaced by provided scope If your component relied on the fact thatcomponents-apidepends onasync-http-client-backend-future,async-http-client-backend-futureshould be added as a provided dependency - #7347 All calls to
org.apache.flink.api.common.functions.RichFunction.open(Configuration), which is deprecated, were replaced with calls toorg.apache.flink.api.common.functions.RichFunction.open(OpenContext) - #7364
- additional, necessary, db schema changes concerning the periodic/scheduling mechanism introduced in #7519
- additionally modified in #7552
- the PeriodicDeploymentManager is no longer a separate DM type
- in
scenarioTypesconfig section, thedeploymentConfigof a periodic scenario type (only Flink was supported so far) may have looked like that:
deploymentConfig: {
type: "flinkPeriodic"
restUrl: "http://jobmanager:8081"
deploymentManager {
db: { <config of the custom db data source> },
processingType: streaming,
jarsDir: ./storage/jars
}
}- changes:
- the
type: "flinkPeriodic"is no longer supported, insteadtype: "flinkStreaming"with additional settingsupportsPeriodicExecution: trueshould be used - the db config is now optional - the periodic DM may still use its custom datasource defined here in
legacyDbsection - when custom
dbsection not defined here, then main Nussknacker db will be used
- the
- config after changes may look like that:
deploymentConfig: {
type: "flinkStreaming"
scheduling {
enabled: true
processingType: streaming
jarsDir: ./storage/jars
}
restUrl: "http://jobmanager:8081"
} - #7335 Deployment managers are loaded using separate class loader (not the Application ClassLoader -
/opt/nussknacker/managers/*should be removed from CLASSPATH definition). The default location for deployment managers jars is themanagersfolder inside the working directory. - #7458 #7534 Flink scenario testing mechanism and scenario state verification mechanism changes
- Scenario testing and scenario state verification is now limited by a timeout to ensure proper resources cleaning. In some cases it might be needed to change the timeout
value. To do that, set
deploymentConfig.scenarioTesting.timeoutor/anddeploymentConfig.scenarioStateVerification.timeoutto desired values. Notice that this properties should be configured along withakka.http.server.request-timeout
- Scenario testing and scenario state verification is now limited by a timeout to ensure proper resources cleaning. In some cases it might be needed to change the timeout
value. To do that, set
- #7468 When a namespace is configured, Kafka consumer groups are also namespaced.
This change should have been introduced as of starting from Nussknacker 1.15 when a feature flag
useNamingStrategyForConsumerGroupIdwas removed to temporarily disable consumer group namespacing. - #7578 Component labels will be auto-generated for all components that don't have
labeldefined inComponentDefinition. Labels will be visible in components palette and in components list. Auto-generated label is created by formating component's name into Title Case, e.g. for component with nameaggregate-session, label will beAggregate Session. If component provider hascomponentPrefixset, it'll be included in auto-generated label. - #7553 #8011
#keyvariable created in window components won't be a list in a string, but it'll have provided types, e.g. instead of"[12.0, ab]"it'll now be[12.0, "ab"]. To keep#keyvalue as before, you'll need to embrace previous values inside curly braces and add.toString, e.g.#input.a#input.b->{#input.a, #input.b}.toString. Also, if you provide one element ingroupByexpression, it will be presented as one element list instead of scalar. - #8011 During scenario compilation, redundant parameters used in node are treated only as warning now. They are skipped and compilation passes.
- #8198 Support for test data without
sourceIdspecified is removed - now, you always have to specify it - #7137#8317 Updated Flink 1.19.2 -> 1.20.2.
- #8209 Nussknacker now requires flink to be run with replaced
lib/flink-scala_2.12-x.x.x.jarbypl.touk:flink-scalalib for the same scala version as used Nussknacker distribution. We provide prebuild flink docker images on Docker Hub - #8478 The behavior of
enumto json encoding has been changed - now it uses.name()instead of.toString() - #8842!13
pl.touk.nussknacker.engine.flink.api.serialization.SerializersRegistrarSPI was moved topl.touk.nussknacker.engine.flink.api.typeinformation.SerializersRegistrar - #8943
spring-jclwas replaced withcommons-logging- projects depending on Nu should update their exclusion rules - #9336
WithKafkaContainerandWithSchemaRegistryContainertest traits were moved from Flink-specificnussknacker-flink-test-utilstonussknacker-kafka-test-utils, methods for accessing service addresses were moved into properContainerobjects - !13
SerializersRegistrarSPI was restored in a new namespace, aspl.touk.nussknacker.engine.flink.api.typeinformation.SerializersRegistrar
The nussknacker-ml jar-carrier image is removed
- The
nussknacker-mljar-carrier image is removed. The mlflow and pmml enricher jars now ship inside the designer image and the lite runtime image at/opt/nussknacker/components/common/, where the default model classpaths already look. Deployments that copied these jars via an init container must remove that init container in the same deploy that adopts this version: removing it earlier silently drops the jars, and keeping it pins an image tag that no longer exists.
The nussknacker-enterprise-extensions jar-carrier image is removed
- The
nussknacker-enterprise-extensionsjar-carrier image is removed; the enterprise jars ship inside the designer and lite runtime images. Extension selection moves to the deploymentCLASSPATH, with one directory per extension underextensions/<name>/*(e.g.extensions/config-loader/*,extensions/configurator-loader/*,extensions/mcp/*,extensions/assistant/*,extensions/nodes-actions/*). Deployments that copied jars from the carrier image via an init container must switch to the baked images in the same deploy as the version bump: removing the init container early drops the jars before the baked image is in place, and bumping the version early pulls anussknacker-enterprise-extensionstag that no longer exists.
In version 1.18.0
Configuration changes
-
- Button name for 'test adhoc' was renamed from
test-with-formtoadhoc-testingIf you are using custom button config remember to update button type totype: "adhoc-testing"inprocessToolbarConfig
- Button name for 'test adhoc' was renamed from
-
- Scenario Activity audit log is available
- logger name,
scenario-activity-audit, it is optional, does not have to be configured - it uses MDC context, example of configuration in
logback.xml:
<logger name="scenario-activity-audit" level="INFO" additivity="false">
<appender-ref ref="STDOUT_FOR_SCENARIO_ACTIVITY_AUDIT"/>
</logger>
<appender name="STDOUT_FOR_SCENARIO_ACTIVITY_AUDIT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - [scenarioId=%X{scenarioId}][version=%X{scenarioVersionId}][user=%X{username}] %msg%n</Pattern>
</encoder>
</appender> -
#6979 Add
type: "activities-panel"to theprocessToolbarConfigwhich replaces removed{ type: "versions-panel" }{ type: "comments-panel" }and{ type: "attachments-panel" } -
#6958 Added message size limit in the "Kafka" exceptionHandler:
maxMessageBytes. Its default value reflects Kafka's default size limit of 1 MB (max.message.bytes), you need to increase it if your error topic allows for larger messages. Remember to add some margin for Kafka protocol overhead (100 bytes should be enough).
Code API changes
- #6971
DeploymentManagerDependenciesAPI changes:- Added field
scenarioActivityManager: ScenarioActivityManager scenarioActivityManagercan be used by anyDeploymentManagerto save scenario activities in the Nu database- there is
NoOpScenarioActivityManagerimplementation available (if needed for tests etc.)
- Added field
- #6971
DeploymentManagercompatible API changes:DeploymentManagermay now optionally extendManagerSpecificScenarioActivitiesStoredByManager- managers extending that trait may internally handle some manager-specific ScenarioActivities and may be queried about those custom activities
- #6695
SingleTypingResultAPI changes:- Renamed
objTypetoruntimeObjTypewhich indicates a current object in a runtime.
- Renamed
- #6766
- Process API changes:
- Field
ScenarioWithDetails.labelswas added - Field
ScenarioWithDetails.tagswas removed (it had the same value aslabelsand was not used)
- Field
- Process API changes:
- #6988 Removed unused API classes:
MultiMap,TimestampedEvictableStateFunction.MultiMapwas incorrectly handled by Flink's default Kryo serializer, so if you want to copy it to your code you should write and register a proper serializer. - #7162 When component declares that requires parameter with either
SpelTemplateParameterEditororSqlParameterEditoreditor, in the runtime, for the expression evaluation result, will be used the newTemplateEvaluationResultclass instead ofStringclass. To access the previousStringuseTemplateEvaluationResult.renderedTemplatemethod. - #7246
- Typing api changes:
- CanBeSubclassDeterminer.canBeSubclassOf changed to AssignabilityDeterminer.isAssignableLoose.
- TypingResult.canBeSubclassOf changed to TypingResult.canBeConvertedTo
- Typing api changes:
REST API changes
- #6944
- New endpoint
/api/scenarioTesting/{scenarioName}/adhoc/validate
- New endpoint
- #6766
- Process API changes:
- PUT
/api/processes/{processName}- optionalscenarioLabelsfield added
- PUT
- Migration API changes:
- POST
/api/migratesupports v2 request format (withscenarioLabelsfield)
- POST
- Process API changes:
- #7021
- Definitions API changes:
- GET
/api/processDefinitionData/*}- added optional query param
enrichedWithUiConfig - added
requiredParamproperty to the response for parameter config atcomponents['component-id'].parameters[*]
- added optional query param
- GET
- Definitions API changes:
- #7246 Changes in DictApiEndpoints:
DictListRequestDtoexpectedType: TypingResultInJson -> Json
Other changes
-
#6692 Kryo serializers for
UnmodifiableCollection,scala.Productetc. are registered based on class of Serializer instead of instance of Serializer. If you have values that were serialized by these Serializers in some state, the state won't be restored after upgrade. -
#6952 Improvement: TypeInformation support for scala.Option: If you used CaseClassTypeInfoFactory with case classes that contain the Option type, the state won't be restored after the upgrade.
-
#6805 Updated Flink 1.18.1 -> 1.19.1. Due to backwards incompatible changes in this Flink version update, Nussknacker 1.18 will not work with Flink versions pre-1.19 right away. If you want to keep using Flink pre-1.19 with current Nussknacker, please refer to compatibility providing plugins in https://github.com/TouK/nussknacker-flink-compatibility.
-
#6912 Improvement: Make TimeMeasuringService usable with other Lifecycle traits
- Services that use
TimeMeasuringServicemust be rebuilt
- Services that use
-
Performance optimization:
- #7058 Add missing Flink TypeInformation for better serialization
- In case of using base (bounded and unbounded) Flink components state will be probably not compatible
FlinkCustomNodeContext.typeInformationDetectionhas been removed, please useTypeInformationDetection.instanceinsteadFlinkCustomNodeContext.forCustomContexthas been removed, please useTypeInformationDetection.instance.forValueWithContextinstead
- #7097 Flink base types registration mechanism
- In case of using types: java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime with CaseClassTypeInfo mechanism, state probably will be lost
- #7058 Add missing Flink TypeInformation for better serialization
-
#7113 Scala 2.13 was updated to 2.13.15, you should update your
flink-scala-2.13to 1.1.2 -
#7187 JSON decoding in
requestsource (request-response processing mode) and inkafkasource (streaming processing mode): For small decimal numbers is used eitherIntegerorLong(depending on number size) instead ofBigDecimal. This change should be transparent in most cases as this value was mostly used after#CONV.toNumber()invocation which still will return aNumber.
In version 1.17.0
Code API changes
- #6248 Removed implicit conversion from string to SpeL
expression (
pl.touk.nussknacker.engine.spel.Implicits). The conversion should be replaced bypl.touk.nussknacker.engine.spel.SpelExtension.SpelExpresion.spel. - #6282 If you relied on the default value of the
topicsExistenceValidationConfig.enabledsetting, you must now be aware that topics will be validated by default (Kafka'sauto.create.topics.enablesetting is only considered in case of Sinks). Create proper topics manually if needed. - Component's API changes
- #6711
SingleComponentConfigchanged toComponentConfigfor better domain naming. Associated functions and objects also changed to...ComponentConfig.... - #6418 Improvement: Pass implicit nodeId to
EagerServiceWithStaticParameters.returnTypeNow methodreturnTypefromEagerServiceWithStaticParametersrequires implicit nodeId param - #6462
CustomStreamTransformer.canHaveManyInputsfield was removed. You don't need to implement any other method in replacement, just remove this method. - #6418 Improvement: Pass implicit nodeId to
EagerServiceWithStaticParameters.returnType- Now method
returnTypefromEagerServiceWithStaticParametersrequires implicit nodeId param
- Now method
- #6340
TestRecordParsertrait used inSourceTestSupporttrait changed to work on lists instead of single records - itsparsemethod now takesList[TestRecord]instead of a singleTestRecordand returns a list of results instead of a single result. - #6520
ExplicitTypeInformationSourcetrait was removed - nowTypeInformationproduced bySourceFunctionpassed toStreamExecutionEnvironment.addSourceis detected based onTypingResult(thanks toTypeInformationDetection)BlockingQueueSource.createtakesClassTagimplicit parameter instead ofTypeInformationEmitWatermarkAfterEachElementCollectionSource.createtakesClassTagimplicit parameter instead ofTypeInformationCollectionSource'sTypeInformationimplicit parameter was removedEmptySource'sTypeInformationimplicit parameter was removed
- #6545
FlinkSink.prepareTestValuewas replaced byprepareTestValueFunction- a non-parameter method returning a function. Thanks to that,FlinkSinkis not serialized during test data preparation.
- #6711
TypingResultAPI changes- #6436 Changes to
TypingResultof SpEL expressions that are maps or lists:TypedObjectTypingResult.valueOptnow returns ajava.util.Mapinstead ofscala.collection.immutable.Map- NOTE: selection (
.?) or operations from the#COLLECTIONShelper cause the map to lose track of its keys/values, reverting itsfieldsto an empty Map
- NOTE: selection (
- SpEL list expression are now typed as
TypedObjectWithValue, with theunderlyingTypedClassequal to theTypedClassbefore this change, and withvalueequal to ajava.util.Listof the elements' values.- NOTE: selection (
.?), projection (.!) or operations from the#COLLECTIONShelper cause the list to lose track of its values, reverting it to a value-lessTypedClasslike before the change
- NOTE: selection (
- #6566
TypedObjectTypingResult.fieldsare backed byListMapfor correctRowTypeInfo's fields order purpose. If #5457 migrations were applied, it should be a transparent change- Removed deprecated
TypedObjectTypingResult.applymethods - should be usedTyped.recordfactory method Typed.recordfactory method takesIterableinstead ofMap
- Removed deprecated
- #6570
TypingResult.canBeSubclassOfgeneric parameter checking related changes. Generic parameters ofTyped[java.util.Map[X, Y]],Typed[java.util.List[X]],Typed[Array[X]]were checked as they were either covariant or contravariant. Now they are checked more strictly - depending on collection characteristic.Keyparameters ofTyped[java.util.Map[Key, Value]]is treated as invariantValueparameters ofTyped[java.util.Map[Key, Value]]is treated as covariantElementparameters ofTyped[java.util.List[Element]]is treated as covariantElementparameters ofTyped[Array[Element]]is treated as covariant
- #6436 Changes to
- #6503
FlinkTestScenarioRunnercleanupsrunWithDataAndTimestampAssignermethod was removed. Instead,timestampAssignerwas added as an optional parameter intorunWithData- new
runWithDataWithTypewas added allowing to test using other types than classes e.g. records
- #6567 Removed ability to set Flink's execution mode
in sources:
TableSource,CollectionSourceand inFlinkTestScenarioRunner.runWithDatamethod. Now you can configure it undermodelConfig.executionModeor for test purposes throughFlinkTestScenarioRunnerBuilder.withExecutionModemethod. - #6610 Add flink node context as parameter to BasicFlinkSink.
Now one can use
FlinkCustomNodeContextin order to build sink inBasicFlinkSink#toFlinkFunctionmethod. - #6635 #6643
TypingResultTypeInformationrelated changesTypingResultAwareTypeInformationCustomisationAPI was removedFlinkCustomNodeContext.typeInformationDetectionis deprecated - useTypeInformationDetection.instanceinsteadFlinkCustomNodeContext.valueWithContextInfo.forCustomContextis is deprecated - useTypeInformationDetection.instance.forValueWithContextinstead
- #6640
BestEffort*Encodernaming changes:- All
BestEffort*Encoderclasses renamed to fitTo<TargetFormat>(SchemaBased)Encodernaming schema JsonToNuStructrenamed toFromJsonDecoder(to fitFrom<SourceFormat>Decodernaming schema)ToJsonEncoderrenamed toToJsonEncoderCustomisationToJsonBasedOnSchemaEncoderrenamed toToJsonSchemaBasedEncoderCustomisation
- All
- #6586 For now on, the SQL enricher automatically converts types as shown below:
- java.sql.Array -> java.util.List
- java.sql.Time -> java.time.LocalTime
- java.sql.Date -> java.time.LocalDate
- java.sql.Timestamp -> java.time.Instant
- java.sql.Clob -> java.lang.String
REST API changes
- #6437 Removed deprecated operation to create a scenario:
POST
/api/processes/{name}/{category}. POST/api/processesshould be used instead. - #6213 Improvement: Load resource config only in test context
WithConfigfromtest-utilsmodules behaviour changes: now it only parses given config, without resolving reference configs, system env variables etc.
Configuration changes
- #6635
globalParameters.useTypingResultTypeInformationparameter was removed. Now we always use TypingResultTypeInformation - #6797
AVRO_USE_STRING_FOR_STRING_TYPEenvironment variable is not supported anymore - we always use String for String type in Avro. If you didn't set up this environment variable, no action is needed
In version 1.16.3
Code API changes
- #6527 Changes to
TypingResultof SpEL expressions that are maps or lists:TypedObjectTypingResult.valueOptnow returns ajava.util.Mapinstead ofscala.collection.immutable.Map- NOTE: selection (
.?) or operations from the#COLLECTIONShelper cause the map to lose track of its keys/values, reverting itsfieldsto an empty Map
- NOTE: selection (
- SpEL list expression are now typed as
TypedObjectWithValue, with theunderlyingTypedClassequal to theTypedClassbefore this change, and withvalueequal to ajava.util.Listof the elements' values.- NOTE: selection (
.?), projection (.!) or operations from the#COLLECTIONShelper cause the list to lose track of its values, reverting it to a value-lessTypedClasslike before the change
- NOTE: selection (
In version 1.16.0
Code API changes
- #6184 Removed
Remote[]string part from forwarded username for scenario creation and updates.processesandprocess_versionstables won't store username with this part anymore increatedByandmodifiedBycolumns. - #6053 Added impersonation mechanism:
OverrideUsernamepermission was renamed asImpersonateand is now used as a global permission.AuthManageris now responsible for authentication and authorization.AuthenticationResourceshandles only plugin specific authentication now. This leads to following changes inAuthenticationResourcesAPI:authenticate()returnsAuthenticationDirective[AuthenticatedUser]and notDirective1[AuthenticatedUser]authenticate(authCredentials)receivesPassedAuthCredentialsparameter type instead ofAuthCredentialsas anonymous access is no longer part ofAuthenticationResourceslogicauthenticationMethod()returnsEndpointInput[Option[PassedAuthCredentials]]instead ofEndpointInput[AuthCredentials]. TheOption[PassedAuthCredentials]should hold the value that will be passed to the mentionedauthenticate(authCredentials).AuthenticationResourcesextendsAnonymousAccessSupporttrait:AnonymousAccessSupporthas one methodgetAnonymousRole()which returns anonymous role name. If you do not want to have an anonymous access mechanism for your authentication method you can extend yourAuthenticationResourcesimplementation withNoAnonymousAccessSupporttrait.
AuthenticationResourceshas a fieldimpersonationSupportof typeImpersonationSupport:ImpersonationSupportis a trait stating whether authentication method supports impersonation. If you don't want impersonation support you can assignNoImpersonationSupportobject to it. If you wish to have it - assignImpersonationSupportedabstract class to it and implementgetImpersonatedUserData(impersonatedUserIdentity)method which returns required user's data for the impersonation by user'sidentity.
AnonymousAccessextendingAuthCredentialswas renamed toNoCredentialsProvided. It does not represent anonymous access to the designer anymore but simply represents passing no credentials.AuthenticationConfigurationhas one additional Boolean propertyisAdminImpersonationPossiblewhich defines whether admin users can be impersonated by users with theImpersonatepermission. The property is set tofalseby default forBasicAuthenticationConfiguration,OAuth2ConfigurationandDummyAuthenticationConfiguration.
- #6087 #6155
DeploymentManagerAPI changes:DMRunDeploymentCommand.savepointPathwas replaced byupdateStrategy: DeploymentUpdateStrategy- In places where
savepointPath = Nonewas passed, theDeploymentUpdateStrategy.ReplaceDeploymentWithSameScenarioName(StateRestoringStrategy.RestoreStateFromReplacedJobSavepoint)should be passed - In places where
savepointPath = Some(path)was passed, theDeploymentUpdateStrategy.ReplaceDeploymentWithSameScenarioName(StateRestoringStrategy.RestoreStateFromCustomSavepoint(path))should be passed
- In places where
DMValidateScenarioCommand.updateStrategywas added- In every place should the
DeploymentUpdateStrategy.ReplaceDeploymentWithSameScenarioName(StateRestoringStrategy.RestoreStateFromReplacedJobSavepoint)should be passed
- In every place should the
deploymentSynchronisationSupportfield was added for purpose of synchronisation of statuses. If synchronisation mechanism is not used in context of given DM, you should returnNoDeploymentSynchronisationSupportobject. The synchronisation mechanism is used by/api/deployments/{deploymentId}/statusendpoint. Other endpoints don't use it.
- #6249
TopicNametrait was introduced and is used in context of specialized topic name (for kafka sources and sinks). Moreover,UnspecializedTopicNamecase class was added and is used in places when the specialization is unknown/not needed.
Configuration changes
- #6082 Default Influx database was changed from
esptonussknacker_metrics
In version 1.15.0
Code API changes
- #5609 #5795 #5837 #5798 Refactoring around DeploymentManager's actions:
- Custom Actions
CustomAction,CustomActionParameterandCustomActionResultmoved fromextension-apitodeployment-manager-apimoduleCustomActionResult.reqwas removedCustomActionwas renamed toCustomActionDefinitionCustomActionRequest(from theextension-api) was renamed toCustomActionCommandCustomActionRequesthas additional comment parameter (like deploy and cancel actions)
- Other "action" methods - all methods operating on a scenario (or its deployment) were replaced by case classes and
one method handling them all:
processCommand(command):validate-DMValidateScenarioCommanddeploy-DMRunDeploymentCommandcancelwithdeploymentIdargument -DMCancelDeploymentCommandcancelwithoutdeploymentIdargument -DMCancelScenarioCommandstopwithdeploymentIdargument -DMStopDeploymentCommandstopwithoutdeploymentIdargument -DMStopScenarioCommandsavepoint-DMMakeScenarioSavepointCommandtest-DMTestScenarioCommand
- "Action type" was renamed to "action name". Loosened the restriction on the name of the action:
ProcessActionType(enum with fixed values) is replaced withScenarioActionName,- in
ProcessActionattributeactionTyperenamed toactionName - in table
process_actionscolumnaction_typeis renamed toaction_name
DeploymentManagerDependencies.deploymentServicewas splitted intodeployedScenariosProviderandactionService- Events renamed:
OnDeployActionSuccessrenamed toOnActionSuccessOnDeployActionFailedrenamed toOnActionFailed
- Custom Actions
- #5762 for the Flink-based TestRunner scenario builder you should replace the last component that was
testResultServicewithtestResultSink - #5783 Return type of
allowedProcessingModemethod inComponenttrait has been changed toAllowedProcessingModestype which is one of:AllowedProcessingModes.Allin case of all processing modes allowedAllowedProcessingModes.SetOf(nonEmptySetOfAllowedProcessingModes)in case only set of processing modes is allowed
- #5757 Refactored API around
FlinkSource- Added
StandardFlinkSourcewith more granular additional traits replacing the need forFlinkIntermediateRawSource - Removed
BasicFlinkSourceandFlinkIntermediateRawSource. Sources extending these traits should now extendStandardFlinkSource. For reference on how to migrate, see changes inFlinkKafkaSourceorCollectionSource - Renamed
FlinkSource'ssourceStreammethod tocontextStream - Removed
EmptySourceFunction
- Added
- #5757 Added support for bounded sources and Flink runtime mode in
Flink tests
CollectionSourcenow takes Flink'sBoundednesswith defaultUnboundedandRuntimeExecutionModewith defaultNoneas a parameters. It's encouraged to set theBoundednessto bounded if applicableBoundednessandRuntimeExecutionModeis also possible to set inFlinkTestScenarioRunnerin new overloadingrunWithDatamethod
Configuration changes
- #5744 Extracted unbounded stream specific components into separate
module:
- Components
periodic,union-memo,previousValue, aggregates, joins anddelayfrombasewere moved intobase-unboundedmodule. They are now built asflinkBaseUnbounded.jarunderwork/components/flink/flinkBaseUnbounded.jar. - Configuration of tumbling windows aggregate offset is changed at the ComponentProvider level:
components.base.aggregateWindowsConfig.tumblingWindowsOffsetshould now be set ascomponents.baseUnbounded.aggregateWindowsConfig.tumblingWindowsOffset - If you previously specified base component jar explicitly in
modelConfig.classPathascomponents/flink/flinkBase.jarand want to retain the unbounded specific components you need to addcomponents/flink/flinkBaseUnbounded.jarexplicitly. - #5887 When using a custom DesignerConfig, ensure that long text elements like 'generate file' are positioned in the last row to prevent excessive spacing between elements.
- Components
Other changes
- #5574 Removed the support for the pluggable expression languages:
ExpressionConfig.languagesremoved - #5724 Improvements: Run Designer locally
- Introduce
JAVA_DEBUG_PORTto run the Designer locally with remote debugging capability - Removed
SCALA_VERSION, please useNUSSKNACKER_SCALA_VERSIONinstead of it
- Introduce
- #5824 Decision Table parameters rename:
- "Basic Decision Table" -> "Decision Table"
- "Expression" -> "Match condition"
- #5881
nussknacker-interpretermodule was renamed tonussknacker-scenario-compiler - #5875 Added configurable idle timeout to Flink Kafka source with the
default value of 3 minutes. You can configure this timeout in Kafka component config at
idleTimeout.durationor disable it atidleTimeout.enabled. You can learn about idleness in Flink general docs and Kafka connector-specific docs - #5875 Removed
useNamingStrategyForConsumerGroupIdfeature flag allowing for disabling namespaced Kafka consumer groups - #5848: Introduced a new method for handling colors, aimed at simplifying customization. Now, all colors are centrally stored in a single location. Refer to README.md for details on theme colors customization.
- #5914 Removed dev-specific configuration files
dev-application.confanddev-tables-definition.sqlfrom public distribution artifacts
In version 1.14.0
Code API changes
- #5271 Changed
AdditionalUIConfigProvider.getAllForProcessingTypeAPI to be more in line with FragmentParameterSingleComponentConfigWithoutIdrenamed toComponentAdditionalConfig- field
params: Map[String, ParameterConfig]changed toparameterConfigs: Map[String, ParameterAdditionalUIConfig] ParameterAdditionalUIConfigis handled analogously toFragmentParameter(expect forvalueCompileTimeValidation, which isn't yet handled)ParameterConfig.defaultValue->ParameterAdditionalUIConfig.initialValueParameterConfig.hintText->ParameterAdditionalUIConfig.hintText- most of the capabilities of
ParameterConfig.editorandParameterConfig.validatorsare covered byParameterAdditionalUIConfig.valueEditorandParameterAdditionalUIConfig.valueCompileTimeValidation
- #5285 Changes around scenario id/name fields:
CanonicalProcess.idof typeStringwas replaced bynamefield of typeProcessNameCanonicalProcess.withProcessIdwas renamed towithProcessNameScenarioWithDetails.idwas removed (it had the same value asname)ScenarioWithDetails.processIdchanged the type toOption[ProcessId]and will have alwaysNonevalueComponentUsagesInScenario.idwas removed (it had the same value asname)ComponentUsagesInScenario.processIdwas removedListenerScenarioWithDetails.idwas removed (it had the same value asname)ValidatedDisplayableProcess.idof typeStringwas replaced bynamefield of typeProcessNameDisplayableProcess.idof typeStringwas replaced bynamefield of typeProcessName,processNamefield is removed- deprecated
AsyncExecutionContextPreparer.prepareExecutionContextwas removed AsyncExecutionContextPreparer.preparenow takesProcessNameinstead ofString
- #5288 #5474 RemoteEnvironment / ModelMigration changes:
ProcessMigration.failOnNewValidationErrorwas removed - it wasn't used anywhere anymoreRemoteEnvironment.testMigrationresult types changesshouldFailOnNewErrorsfield was removed - it wasn't used anywhere anymoreconvertedfield was replaced by theprocessNamefield which was the only information that was used
RemoteEnvironment.migratetakesScenarioParametersinstead ofcategory
- #5361
Parameterhas new, optionallabelOptfield which allows to specify label presented to the user without changing identifier used in scenario graph json (Parameteter.name) - #5356 Changes in AdditionalUIConfigProvider.getAllForProcessingType now require model reload to take effect.
- #5393 #5444
- Changes around metadata removal from the REST API requests and responses:
DisplayableProcesswas renamed toScenarioGraphScenarioGraphfields that were removed:name,processingType,category- all these fields already were inScenarioWithDetailsProcessPropertiesfield removed:isFragment- this field already was inScenarioWithDetailsScenarioWithDetailsfieldjson.validationResultwas moved into the top level ofScenarioWithDetailsScenarioWithDetailsfieldjsonwas renamed intoscenarioGraphand changed the type intoScenarioGraphValidatedDisplayableProcesswas renamed toScenarioGraphWithValidationResultScenarioGraphWithValidationResultall scenario graph fields were replaced by onescenarioGraph: DisplayableProcessfield
- Migration mechanisms (
RemoteEnvironmentandTestModelMigrations) useScenarioWithDetailsForMigrationsinstead ofScenarioWithDetails
- Changes around metadata removal from the REST API requests and responses:
- #5424 Naming cleanup around
ComponentId/ComponentInfoComponentInfowas renamed toComponentIdComponentIdwas renamed toDesignerWideComponentId- new
ComponentIdis serialized in json to string in format$componentType-$componentNameinstead of separate fields (nameandtype) NodeComponentInfo.componentInfowas renamed tocomponentId
- #5438 Removed sealed trait
CustomActionError, nowCustomActionResultis always used - #5465 #5457 Typed related changes
CommonSupertypeFindershouldn't be created directly anymore -CommonSupertypeFinder.*predefined variables should be used instead, in most cases just (CommonSupertypeFinder.Default)TypedObjectTypingResult.applyremoved legacy factory method takingList[(String, TypingResult)]- should be used variant withMapTypedObjectTypingResult.applyremoved legacy factory method takingTypedObjectDefinition- should be used variant withMapTypedObjectTypingResult.applyis deprecated - should be usedTyped.record(...)instead. It will be removed in further releasesTypedObjectDefinitionwas removedTyped.emptywas removed,TypedUnionnow handles only >= 2 typesTyped.apply(vararg...)was replaced byTyped.apply(NonEmptyList)andTyped.apply(firstType, secondType, restOfTypesVaraarg...)If you have a list of types and you are not sure how to translate it toTypingResultyou can try to useTyped.fromIterableOrUnknownIfEmptybut it is not recommended - see docs next to it.TypedUnionis not a case class anymore, but is still serializable - If it was used in a Flink state, state will be probably not compatible
- #5517 Legacy
OnFinishedlistener-api event was removed - #5474
Componentclass now need to specifyallowedProcessingModes. Most of the implementations (CustomStreamTransformer,Service,SinkFactory) has default wildcard (None). ForSourceFactoryyou need to specify whichProcessingModethis source support. You have predefined traits:UnboundedStreamComponent,BoundedStreamComponent,RequestResponseComponent,AllProcessingModesComponentthat can be mixed into the component - #5474 Changes around new scenario metadata (aka "parameters"):
ScenarioWithDetails: addedprocessingModeandengineSetupNamefields
- #5522, #5521, #5519
DeploymentManagerAPI related changes:- In the
DeploymentManager:DeploymentManager.getProcessState(ProcessIdWithName, Option[ProcessAction])become final. You should implementresolvemethod instead. It does the same, onlyList[StatusDetails]are already determined.- Method
DeploymentManager.getProcessStatessignature was changed and now requires an implicitfreshnessPolicy: DataFreshnessPolicy - Trait
AlwaysFreshProcessStateand methodgetFreshProcessStateswere removed, instead of it please usegetProcessStateswithDataFreshnessPolicy.Freshpolicy - Managers
FlinkStreamingRestManagerandFlinkRestManagerrequire new parameter:scenarioStateCacheTTL: Option[FiniteDuration]
- In the
DeploymentManagerProvider:- New methods were added:
defaultEngineSetupNameandengineSetupIdentity. They have default implementations, you should consider to replace them by your own - New, overloaded
createDeploymentManagerwas added. In the new one most of the parameters were bundled intoDeploymentManagerDependenciesclass which allows to easier pass these dependencies to delegates. Also, this method returnsValidateNel[String, DeploymentManager]. You can return errors that will be visible to users e.g. invalid configuration etc. The old one is deleted. - Method
createDeploymentManagersignature was changed and now requires new parameter:scenarioStateCacheTTL: Option[FiniteDuration]
- New methods were added:
- In the
- #5526 Refactored namespaces:
- Removed
ObjectNamingSPI - Removed logging when using naming strategy
- Replaced
ObjectNamingwith singleNamingStrategywhich prepares a name with a prefix fromnamespacekey fromModelConfigor returns the original name if the value is not configured
- Removed
- #5535
ProcessingTypeConfig.classpathcontains now raw,Stringentries instead ofURL. TheStringtoURLconverting logic is now insideModelClassLoader.apply
- #5505 anonymous access functionality for Tapir-based API
AuthenticationResources&AnonymousAccesstraits were changed to be able to introduce anonymous access featureAuthCredentialsclass was changed too
- #5373#5694 changes related to
Components andLazyParameters:LazyParametercan be evaluated on request thanks to itsevaluatemethodParamsdata class was introduced as a replacement for runtime parameters values defined asMap[String, Any].Paramsdata class, in its extraction methods, assumes that a parameter with the given name exists in the underlying Map.TypedExpressionwas removed fromBaseDefinedParameterhierarchy in favour ofTypingResultTypedExpressiondoesn't depend onExpressionTypingInfoanymoreServiceInvokerrefactoring (parameters map was removed, a context is passed to its method)ProcessListenerinterface changed slightlyParameterWithExtractorutil was replaced withParameterDeclaration.- classes renaming:
LazyParameterInterpretertoLazyParameterInterpreterGenericNodeTransformationtoDynamicComponentSingleInputGenericNodeTransformationtoSingleInputDynamicComponentJoinGenericNodeTransformationtoJoinDynamicComponentJavaGenericTransformationtoJavaDynamicComponentJavaGenericSingleTransformationtoJavaSingleInputDynamicComponentJavaGenericJoinTransformationtoJavaJoinDynamicComponentJavaSourceFactoryGenericTransformationtoJavaSourceFactoryDynamicComponentGenericContextTransformationWrappertoDynamicComponentWrapperSingleGenericContextTransformationWrappertoSingleInputDynamicComponentWrapperSourceFactoryGenericContextTransformationWrappertoSourceFactoryDynamicComponentWrapperJoinGenericContextTransformationWrappertoJoinDynamicComponentWrapper
- type
NodeTransformationDefinition(insideDynamicComponent) renamed toContextTransformationDefinition
- #5641
PeriodicProcessDeployment/DeploymentWithJarData/PeriodicProcessnow takes type parameterCanonicalProcessorUnitto point out whether it contains scenario json. - #5656
pl.touk.nussknacker.engine.api.expression.Expression#languagemethod returnsLanguagetrait instead ofString - #5707
ParameterNamedata class was introduced. It replacesStringin whole places where it's used as a parameter name - #5754 Fix for broken encoding mechanism in tests from file with Avro format, revert [0d9b600][https://github.com/TouK/nussknacker/commit/0d9b600]
- Classes
ResultsCollectingListener,TestResults,ExpressionInvocationResult,ExternalInvocationResultdepend onT - Classes
TestResults.nodeResultsusesResultContextinstead ofContext - Classes
TestResults.exceptionsusesExceptionResultinstead ofNuExceptionInfo - Added
variableEncodertoResultsCollectingListenerHolder.registerRun
- Classes
REST API changes
- #5280#5368 Changes in the definition API:
/api/processDefinitionData/componentIdsendpoint is removed/api/processDefinitionData/*response changes:services,sourceFactories,sinkFactories,customStreamTransformersandfragmentInputsmaps fields were replaced by onecomponentsmap with key in format$componentType-$componentNameand moved into top level of responsetypesInformationfield was renamed intoclasses, moved into top level of response and nestedclazzNameinside each element was extractedcomponentsConfigfield was removed - now all information about components are available in thecomponentsfieldnodeIdfield insideedgesForNodeswas renamed intocomponentIdin the flat$componentType-$componentNameformatdefaultAsyncInterpretationfield was removed
- #5285 Changes around scenario id/name fields:
/api/process(Details)/**endpoints:idfields was removed (it had the same value asname)processIdfields return alwaysnull.json.idfields was renamed to.json.name
/api/components/*/usagesendpoint:idfields was removed (it had the same value asname)processIdfields was removed
/api/processes/**/activity/attachments-processIdfields was removed/api/processes/**/activity/comments-processIdfields was removed- GET
processes/$name/$version/activity/attachments-$versionsegment is removed now
- #5393 Changes around metadata removal from the REST API requests and responses:
/api/processValidationwas changed to/api/processValidation/$scenarioNameand changed request type/api/testInfo/*was changed to/api/testInfo/$scenarioName/*and changed request format regarding code API changes/api/processManagement/generateAndTest/$sampleswas changed to/api/processManagement/generateAndTest/$scenarioName/$samples/api/processesExport/*was changed to/api/processesExport/$scenarioName/*and changed response format regarding code API changes/api/processes/import/$scenarioNamewas changed response into{"scenarioGraph": {...}, "validationResult": {...}- GET
/api/processes/*and/api/processesDetails/*changed response format regarding code API changes - PUT
/api/processes/$scenarioNamewas changed request field fromprocesstoscenarioGraph /api/adminProcessManagement/testWithParameters/$scenarioNamewas changed request field fromdisplayableProcesstoscenarioGraph
- #5424 Naming cleanup around
ComponentId/ComponentInfo- Endpoints returning test results (
/api/processManagement/test*) returnnodeIdinstead ofnodeComponentInfonow /processDefinitionData/*response: fieldtypewas replaced bycomponentIdinside the path.componentGroups[].components[]
- Endpoints returning test results (
- #5462
/api/processes/category/*endpoint was removed - #5474 POST
/api/processes/$scenarioName/$category?isFragment=$isFragmentresource become deprecated. It will be replaced by POST/processeswith fields:name,isFragment,forwardedUserName,category,processingMode,engineSetupName. Three last fields are optional. Please switch to the new API because in version 1.5, old API will be removed. - POST
/api/nodes/$scenarioName/validationresponse for object invalidationErrorsarray can havedetailsof the error
Configuration changes
- #5297
componentsUiConfigkey handling change:$processingType-$componentType-$componentNameformat was replaced by$componentType-$componentNameformat
- #5323 Support for the legacy categories configuration format was removed.
In the new format, you should specify
categoryfield inside each scenario type. - #5419 Support for system properties was removed from model configuration (they aren't resolved and added to merged configuration)
- #5474 You have to ensure that in every scenarioType model's
classPath, in every jar are only components with not colliding processing modes. Also at least one component has defined processing mode other than wildcard. On the other hand starting from this version, you can use the same category for many scenarioTypes. You only have to ensure that they have components with other processing modes or other deployment configuration. - #5558 The
processToolbarConfigtoolbar withtype: "process-info-panel"no longer accepts thebuttonsproperty. It only display scenario information now. However, a new toolbar withtype: "process-actions-panel"has been introduced, which does accept thebuttonsproperty and renders actions similar to the oldtype: "process-info-panel".
Helm chart changes
- #5515 #5474 Helm chart now has two preconfigured scenario types (
streamingandrequest-response) instead of one (default). Because of that, scenario created using previous version of helm chart will have invalid configuration in the database. To fix that, you have to manually connect to the database and execute sql statement:UPDATE processes SET processing_type = 'given-scenario-type' where processing_type = 'default';
Other changes
- #4287 Cats Effect 3 bump Be careful with IO monad mode, we provide an experimental way to create IORuntime for the cat's engine.
- #5432 Kafka client, Confluent Schema Registry Client and Avro bump
- #5447 JDK downgraded from 17 to 11 in lite runner image for scala 2.13
- #5465 Removed
strictTypeCheckingoption andSupertypeClassResolutionStrategy.Unionused behind it - #5517 Removed legacy mechanism marking scenario finished based on the fact that the last action was deploy and job was finished. The new mechanism leverage deployment id which was introduced in #4462 in 1.11 version.
- #5474 The mechanism allowing migration between two environments uses by default the new,
scenario creating API. In case when the secondary environment is in the version < 1.14, you should switch
secondaryEnvironment.useLegacyCreateScenarioApiflag to on. - #5526 Added namespacing of Kafka consumer group id in both engines.
If you have namespaces configured, the consumer group id will be prefixed with
namespacekey from model config - in that case a consumer group migration may be necessary for example to retain consumer offsets. For gradual migration, this behaviour can be disabled by settinguseNamingStrategyInConsumerGroups = falseinKafkaConfig. Note that theuseNamingStrategyInConsumerGroupsflag is intended to be removed in the future.
In version 1.13.1
Code API changes
- #5447 JDK downgraded from 17 to 11 in lite runner image for scala 2.13
In version 1.13.0
Code API changes
- #4988 Method definition
def authenticationMethod(): Auth[AuthCredentials, _]was changed todef authenticationMethod(): EndpointInput[AuthCredentials] - #4860 DeploymentManagerProvider implementations have to implement the method
def scenarioPropertiesConfig(config: Config): Map[String, ScenarioPropertyConfig]instead ofdef additionalPropertiesConfig(config: Config): Map[String, AdditionalPropertyConfig] - #4919 Improvement: Support for handling runtime exceptions at FlinkTestScenarioRunner:
TestProcess.exceptionstype changed fromList[ExceptionResult[T]]toList[NuExceptionInfo[_ <: Throwable]]
- #4912 Changes in scenario details:
pl.touk.nussknacker.restmodel.processdetails.BaseProcessDetails[_]andpl.touk.nussknacker.restmodel.processdetails.BasicProcessused in rest resources were merged intopl.touk.nussknacker.restmodel.scenariodetails.ScenarioWithDetailspl.touk.nussknacker.restmodel.processdetails.BaseProcessDetails[_]used inpl.touk.nussknacker.ui.listener.services.PullProcessRepositorywere moved intolistener-apiand renamed intopl.touk.nussknacker.ui.listener.ListenerScenarioWithDetailspl.touk.nussknacker.restmodel.processdetails.ProcessDetailsandpl.touk.nussknacker.restmodel.processdetails.ValidatedProcessDetailstype aliases are not available anymore - you should probably useScenarioWithDetailsin these placespl.touk.nussknacker.restmodel.processdetails.ProcessVersionwas moved intopl.touk.nussknacker.engine.api.process.ScenarioVersionpl.touk.nussknacker.restmodel.processdetails.StateActionsTypeswas moved intoProcessActionType.StateActionsTypes
- #4959
listener-apimodule become decoupled fromrestmodelmodule. Some classes were moved toextensions-apimodule to make it possible:pl.touk.nussknacker.restmodel.displayedgraphpackage was renamed topl.touk.nussknacker.engine.api.displayedgraphpl.touk.nussknacker.restmodel.displayedgraph.ValidatedDisplayableProcesswas moved topl.touk.nussknacker.restmodel.validationpackagepl.touk.nussknacker.restmodel.process.ProcessingTypewas moved topl.touk.nussknacker.engine.api.processpackagepl.touk.nussknacker.restmodel.scenariodetails.ScenarioVersionwas moved topl.touk.nussknacker.engine.api.processpackage
- #4745 Added method
ScenarioBuilderto create fragments with specified input node id instead of taking a default from fragment id - #4745 Add more errors for scenario and node id validation and change names, messages of existing ones
- #4928 #5028
Validator.isValidmethod now takesexpression: Expression, value: Option[Any]instead ofvalue: Stringwhich was not really value, but expression. Straight-forward migration is to change method definition and now useexpression.expressioninstead ofvalueif your validator depends on raw expression. If validator was doing quasi-evaluation, for example trimming'to get string, you can just takevalueand cast it to desired class.LiteralNumberValidatoris removed, to achieve same result useCompileTimeEvaluableValueValidatorwith parameter ofNumbertype,LiteralIntegerValidatoris considered deprecated and will be removed in the future, to achieve same result useCompileTimeEvaluableValueValidatorwith parameter ofIntegertype,LiteralRegExpParameterValidatoris renamed toRegExpParameterValidator- annotation
pl.touk.nussknacker.engine.api.validation.Literalwas renamed topl.touk.nussknacker.engine.api.validation.CompileTimeEvaluableValue
- #5079
AuthCredentialsis moved topl.touk.nussknacker.securityinextensions-api - #5103
- Values of
ExpressionConfig.globalImportsandExpressionConfig.dictionariesaren't wrapped withWithCategoriesanymore WithCategories.applywithcategoriesvarrag variant is replaced by version with headcategoryand tailcategoriesvarrag Previous version was commonly wrongly used as an "object without categories specified" but in fact it was "object with empty categories list" which means that object should be never visible. To create "object without categories specified" use,WithCategories.anyCategory. If you want to pass just a list of categories, useWithCategories(value, Some(list), SingleComponentConfig.zero)
- Values of
- #5171 Changes around
ComponentTypevalues changes:- In
ComponentTypevalues:- Built-in component's artificial component types (
Filter,Split,Switch,Variable,MapVariable) were replaced byBuiltIntype ProcessorandEnrichercomponent types were replaced byServiceFragmentswas replaced byFragmentCustomNodewas replaced byCustomComponent
- Built-in component's artificial component types (
- In
ComponentInfo: Order of parameters swapped + names of them changedcomponentType->type,componentName->name
- In
- #5209 Now
TestScenarioRunnerdoesn't load components fromComponentProviderautomatically. Instead, it loads some predefined set of components. Rest of them you need to pass components usingwithExtraComponentsmethod. Components loaded automatically:TestScenarioRunner.liteBased- frombaseproviderTestScenarioRunner.kafkaLiteBased- frombaseandkafkaprovidersTestScenarioRunner.requestResponseBased- frombaseandrequestResponseprovidersTestScenarioRunner.flinkBased- frombaseproviderTestScenarioRunnernow also uses global variables from default model
- #4956 Refactor: Cleanup TestResults
- Changed signature
DeploymentManager.testmethod, and removedvariableEncoderparam - Classes
TestResults,ExpressionInvocationResult,ExternalInvocationResultdon't depend onT - Classes
NodeResultis removed. Instead,Contextis used directly - Removed
variableEncoderfromResultsCollectingListenerHolder.registerRun - Removed
ResultContext, please useContextinstead of it
- Changed signature
- #5240 Simpler result types in
TestScenarioRunnerRunResultandRunUnitResulthas no generic parameter anymoreRunResultand its descendants has nosuccessmethod anymore - forRunListResultshould be usedsuccessesinstead
REST API changes
- #4745 Change
api/properties/*/validationendpoint request type- Replace
processPropertieswithadditionalFields - Add
idfield for scenario or fragment id
- Replace
- #5039#5052 Changes in endpoints
api/parameters/*/suggestionsrequestvariablesis renamed tovariableTypesand it should have only local variables now
api/processes/**response.json.validationResult.nodeResults.variableTypesdoesn't contain global variables types anymore
api/processDefinitionData/*response.processDefinition.globalVariablesis removed
api/parameters/*/validaterequestscenarioNameis removedprocessPropertiesis removed
Configuration changes
- #4860 In file-based configuration, the field
scenarioTypes.<scenarioType>.additionalPropertiesConfigis renamed toscenarioTypes.<scenarioType>.scenarioPropertiesConfig - #5077 In SQL enricher configuration,
connectionPropertieswas changed todataSourceProperties
Other changes
- #4901 Improvements TestScenarioRunner:
- Changes at
FlinkProcessRegistrar.registerpassingresultCollectorinstead oftestRunId
- Changes at
- #5033 Scala 2.13 was updated to 2.13.12, you may update your
flink-scala-2.13to 1.1.1 (it's not required, new version is binary-compatible) - #5059 #5100 Categories configuration doesn't allow configuring multiple categories for the same scenario type. If you have such a case, you have to extract another scenario types and assign each category to each scenario type. Because of this change configuration of categories was also removed from Components configuration
- #4953 Stricter validation in base components:
- Boolean expressions in
SwitchandFilternodes are required not null values - Variable values in
MapVariable,FragmentOutputandVariableare mandatory - Field names in
MapVariable,FragmentOutputare required to be unique
- Boolean expressions in
- #4698 Due to change in program argument encoding all scheduled batch scenarios handled by periodic DM must be cancelled before upgrade
In version 1.12.6
Other changes
- #5447 JDK downgraded from 17 to 11 in lite runner image for scala 2.13
In version 1.12.x
Code API changes
- #4574 Improvements: at
KafkaClientandRichKafkaConsumerin kafka-test-utilsRichKafkaConsumer.consumeWithJsonneeds json decoder- removed
RichKafkaConsumer.consumeWithConsumerRecord, useRichKafkaConsumer.consumeWithJsoninstead of it RichKafkaConsumer.defaultSecondsToWaitrenamed toRichKafkaConsumer.DefaultSecondsToWaitKafkaClient.sendMessageaccepts generic content with json encoder
- #4583
DeploymentManagerhas new variants of methodcancelandstoptakingDeployomentIdnext toProcessName. They will be used with batch processing mechanism (periodic DM) so it is necessary to implement it only if your DM will be wrapped byPeriodicDeploymentManager - #4685 In
AuthenticationResourcestrait it was added two new methods that have to be implemented in the child classes:def authenticationMethod(): Auth[AuthCredentials, _]anddef authenticate(authCredentials: AuthCredentials): Future[Option[AuthenticatedUser]]. The first one tells what authentication method will be used (it's for Tapir-based API purposes) and the latter one is the authentication action itself. Thedef authenticate(): Directive1[AuthenticatedUser]should be treated as deprecated. It's used in the NU APIs which are still Akka HTTP-based. When we get rid of Akka HTTP, it will be removed. - #4762 Rename
RegExpParameterValidatortoLiteralRegExpParameterValidator
REST API changes
- #4697 Change
api/parameters/*/validateandapi/parameters/*/suggestionsendpoints.- Use
processingTypeinstead ofprocessName - Add
scenarioNameparameter toParametersValidationRequestused inapi/parameters/*/validate
- Use
- #4602 Cleaning subprocess usages after NU 1.11 release
- Removed isSubprocess endpoint param, use isFragment from now on.
- Removed backward compatibility for subprocess fields.
Other changes
- #4492 Allow testing fragments using ad-hoc testing method.
By default, NU enables that feature but if you have some custom
processToolbarConfigsettings then You would like to removehidden: { fragment: true }flag fortype: "test-with-form",type: "test-counts"andtype: "test-hide"insideprocessToolbarConfig -> "test-panel".
In version 1.11.0
Code API changes
- #4295
DeploymentManager.getProcessState(ProcessName)method now returnsList[StatusDetails]instead ofOption[StatusDetails]. If you are a consumer of this API and want to have the same behavior as previously, you can useInconsistentStateDetector.extractAtMostOneStatusmethod for that. Notice, that in the future visibility of this method may be changed into private. - #4462
StatusDetails.deploymentIdfield changed type intoOption[DeploymentId]. It contains, internal designer's deployment id. It is used to assign deployment on runtime side with deployment action on designer side in periodic DM for purpose of correct status synchronization. If you want to make it filled, you should pass the correct value inDeploymentData.deploymentId. Current value ofdeploymentId: Option[ExternalDeploymentId]was moved intoexternalDeploymentIdfield.ProcessActionhas a new field -id.ProcessStateDefinitionManager.processStatevariant of methods with multiple parameters was removed - you should useProcessStateDefinitionManager.processState(StatusDetails)variant instead. - #4353 Removed isCancelled/isDeployed flags based on
ProcessAction,ProcessAction.actionrenamed to actionType. TraitProcessis removed. - #4484
ProcessIdWithNamemoved from packagepl.touk.nussknacker.restmodel.processtopl.touk.nussknacker.engine.api.processDeploymentManager.getProcessState(ProcessName, Option[ProcessAction])method now takesProcessIdWithNameas an argument instead ofProcessName. The same withPostprocessingProcessStatus.postprocess.
REST API changes
- #4454 Rename 'subprocess' to 'fragment' along with all endpoints (with backward compatibility).
isSubprocessquery parameter is renamed toisFragment.isSubprocesswill be removed in 1.12.0
- #4462 Process state API returns
externalDeploymentIdinstead ofdeploymentId.
Other changes
- #4514
AkkaHttpBackendin designer is replaced byAsyncHttpClientFutureBackend. To use custom http client configuration useahc.propertiesfile and make sure it is available in the classpath.
In version 1.10.0
Code API changes
- #4352
TypedObjectTypingResult#fieldsare no longer ordered, fields will be sorted for presentation (seeTypedObjectTypingResult#display) - #4294
HttpRemoteEnvironmentConfigallows you to pass flagpassUsernameInMigration- (default true). When set to true, migration attaches username in the form ofRemote[userName]while migrating to secondary environment. To use the old migration endpoint, set to false. - #4278 Now expression compiler and code suggestions mechanism are reusing the same
types extracted based on model. Before the change types in compiler were lazily extracted. Because of this change, some expressions
can stop to compile. You may need to add
WithExplicitTypesToExtractto some of yoursSourceFactoryimplementations. See extending classes for examples on how to implement it. - #4290 Renamed predicates used in
ClassExtractionSettings:ClassMemberPatternPredicaterenamed toMemberNamePatternPredicateAllMethodNamesPredicaterenamed to AllMembersPredicate
- #4299, #4300
StateStatusis identified by its name.ProcessStateserialization uses this name as serialized state value.
Sealed traitStateStatusis unsealed, all members are replaced by correspondingSimpleStateStatusstate definitions, custom statuses are defined within eachProcessStateDefinitionManager.ProcessActionis moved from restmodel to extensions-api, package engine.api.deployment. - #4339 Improvements: Don't fetch state for archived/unarchived scenario, return computed based on last state action At BaseProcessDetails we provide lastStateAction field which can have an influence on the presented state of the scenario. We currently use it to distinguish between cancel / not_deployed and to detect inconsistent states between the designer and engine
- #4302 State inconsistency detection was moved from designer to DeploymentManager.
DeploymentManager.getProcessStatefor internal purposes returnsOption[StatusDetails]which is based on job status from deployment manager (instead ofOption[ProcessState]which contains UI info). There is separategetProcessStatethat returnsProcessStatewhich is a status from engine resolved viaInconsistentStateDetectorand formatted with UI-related details.PeriodicProcessEventusesStatusDetailsinstead ofProcessState. Constants defined inProblemStateStatusare renamed to match UpperCamelCase formatting. - #4350
StateStatus.isDuringDeploy,StateStatus.isFinished,StateStatus.isFailed,StateStatus.isRunning,ProcessState.isDeployedmethods were removed. Instead, you should compare status with specific status. - #4357 Changed structure of
MetaDatainCanonicalProcess-TypeSpecificDataautomatically migrated toProcessAdditionalFields- Example MetaData structure before migration:
{
"id": "scenarioName",
"typeSpecificData": {
"parallelism": 1,
"spillStateToDisk": true,
"checkpointIntervalInSeconds": null,
"type": "StreamMetaData"
},
"additionalFields": {
"description": null,
"properties": {
"someCustomProperty": "someCustomValue"
}
}
}- Example MetaData structure after migration:
{
"id": "scenarioName",
"additionalFields": {
"description": null,
"properties": {
"parallelism" : "1",
"spillStateToDisk" : "true",
"useAsyncInterpretation" : "",
"checkpointIntervalInSeconds" : "",
"someCustomProperty": "someCustomValue"
},
"metaDataType": "StreamMetaData"
}
}
Configuration changes
- #4283 For OIDC provider,
accessTokenIsJwtconfig property is introduced, with default valuesfalse. Please mind, that previous Nussknacker versions assumed its value is true ifauthentication.audiencewas defined. - #4357
TypeSpecificDataproperties are now be configured inDeploymentManagerProvider:- Main configuration is done through
additionalPropertiesConfiglike other additional properties - Initial values overriding defaults from the main configuration can be set in
metaDataInitializer
- Main configuration is done through
Other changes
- #4305
scala-compilerandscala-reflectare now included inflink-scala, so you can simplify your deployment by removing them and updating to new (flink-scalaJAR) (this doesn't introduce any functional changes)
REST API changes
- #4350
deleteaction is available only for archived scenarios. Before the change it was checked that scenario is not running
In version 1.9.0
Code API changes
- #4030 Changes for purpose of local testing of designer with other urls than on engine side
ProcessingTypeConfig.modelConfignow containsConfigWithUnresolvedVersioninstead ofConfig. OldConfigvalue is inConfigWithUnresolvedVersion.resolvedModelConfigLoader.resolveInputConfigDuringExecutiontakesConfigWithUnresolvedVersioninstead ofConfig. UseConfigWithUnresolvedVersion.applyfor easy transition between those classes
- #3997 Removal of obsolete
subprocessVersions. It affectsMetaData,ProcessMetaDataBuilderandDisplayableProcessproperties. - #4122, #4132, #4179, #4189
- Use
ProcessStateDefinitionManager.stateDefinitionsto describe states: 1) their default properties 2) how the states are presented in filter-by-status options.
(see an example of basic definitions inSimpleProcessStateDefinitionManagerandSimpleStateStatus). - State defaults and allowed actions are moved to
SimpleStateStatus,FlinkStateStatus,PeriodicStateStatus,EmbeddedStateStatusandK8sStateStatusfrom corresponding state-definition-managers (see exampleFlinkProcessStateDefinitionManager). - Type
CustomStateStatus.namerenamed toStatusName ProcessResourcesexposes new endpoint/api/procecesses/statusDefinitions- Within the base set of statuses used in Embedded, Flink, K8 and Periodic mode (
SimpleStateStatus), statusesFailing,Failed,Error,Warning,FailedToGetandMulipleJobsRunningare replaced by oneProblemStateStatuswhich is parametrized by specific message.ProblemStateStatusprovides several builder methods, one for each corresponding removed state. Those builders allow to preserve the exact moments when each state appears in the scenario lifecycle. - Displayed tooltip and description of
ProblemStateStatushave the same value. - Removed
SimpleStateStatus.Unknown - Removed status
FailedStateStatus. UseProblemStateStatusinstead. - Status configuration for icon, tooltip and description is obligatory.
- Use
- #4104
DeploymentManager.findJobStatuswas renamed togetProcessState. NewDataFreshnessPolicyparameter was added. Returned type was changed toWithDataFreshnessStatus[T]whereTis the previous value andcached: Booleanis additional information that should be provided. If you provideDeploymentManagerwhich communicate remotely with some service, and you want to use standard build-in caching forProcessState, wrap yourDeploymentManagerusingCachingProcessStateDeploymentManager.wrapWithCachingIfNeededin yourDeploymentManagerProvider. Thanks to that, caching will be handled as expected, and yourDeploymentManagerjust should extendAlwaysFreshProcessStatewhich provide the same interface as the previous one, with only method name changed. Especially, when you use 'PeriodicDeploymentManagerProvider',delegateshould already returnDeploymentManagerwrapped by caching mechanism. - #4131
Parameter.defaultValuenow holdsOption[Expression]instead ofOption[String]. You have to wrap aStringwithExpression.spel() - #4224 If you're using Flink with Nussknacker built with Scala 2.13, add this
jar in your Flink installation to
libdir. It's our implementation oforg.apache.flink.runtime.types.FlinkScalaKryoInstantiator(sources are here) which is needed to properly (de)serialize Flink state when using scala 2.13. Hopefully, it's temporary solution, until Flink becomes really scala-free and gets rid of thisFlinkScalaKryoInstantiatorclass or allows to have it in the job code (not Flink libs). - #4190 - introduced possibility to configure offset in
FlinkComponentsProvider(components.base.aggregateWindowsConfig.tumblingWindowsOffset, by default 0) for aggregates with tumbling windows. You might want to set it up, especially when you want your daily windows to be aligned according to your timezone if it's not UTC. See example in Flink docs
Other changes
- #4122, #4132 Changes in state definitions:
- In
ProcessStateDefinitionManagerdefault behaviour of methodsstatusTooltip,statusDescriptionandstatusIconis to return default properties defined viastateDefinitions. It is not necessary to override those methods when all definitions have fixed default properties. - To introduce custom status properties, extensions to basic definitions, use
OverridingProcessStateDefinitionManager. OverridingProcessStateDefinitionManagerallows to specify delegate (previously onlySimpleProcessStateDefinitionManagerwas available) and custom state definitions.- Parameter
delegateinOverridingProcessStateDefinitionManagerhas no default value, it should be provided explicitly. - There is additional validation when all processing types are reloaded from configuration: check if all processing types state definitions configuration is correct.
(see comment in
ProcessStateDefinitionService)
- In
- #3997 Due to removal of deprecated field
subprocessVersionsmigration of scenarios from and to remote environment, for Nussknacker version 1.9.0+ and older will not be possible. Use export and import as a workaround while working between older and newer version.
Other changes
- #3675 Improvements: Normalize kafka components params name
- Renamed kafka topic param name from
topictoTopic - Renamed kafka value param name from
valuetoValue
- Renamed kafka topic param name from
In version 1.8.0
Scenario authoring changes
- #3924
- Fixup:
{}is now interpreted as "allow everything schema", not as "object schema". Objects schemas have to have declared"type": "object". - Unknown is now allowed on sinks in both validation modes if output schema is "everything allowed schema".
- Fixup:
Code API changes
- #3924 - changes to
SwaggerTypedhierarchySwaggerMap(valuesType)->SwaggerObject(Map.empty, additionalProperties = AdditionalPropertiesEnabled(valuesType))AdditionalPropertiesSwaggerTyped->AdditionalPropertiesEnabledAdditionalPropertiesWithoutType->AdditionalPropertiesEnabled(SwaggerAny)SwaggerRecursiveSchema/SwaggerUnknownFallback->SwaggerAny
Other changes
-
#3835 Removed Signals and QueryableState. This change affects:
- Configuration
- Components and DeploymentManager API
- REST API
-
#3823, #3836, #3843 - scenarios with multiple sources can be tested from file
TestDataGenerator#generateTestDatareturns JSON test records instead of raw bytes. Test records are serialized to a file by designer Test record can optionally contain timestamp which is used to sort records generated by many sourcesTestDataParserwas replaced withTestRecordParserthat turns a single JSON test record into a source recordTestData.newLineSeparatedhelper was removed. Scenario test records have to be created explicitly. Each scenario test record has assigned sourceDeploymentManager#testtakesScenarioTestDatainstead ofTestData- Designer configuration
testDataSettings.testDataMaxBytesrenamed totestDataMaxLength
-
#3916 Designer configuration
environmentAlert.cssClassrenamed toenvironmentAlert.color -
#3922 Bumps: jwks: 0.19.0 -> 0.21.3, jackson: 2.11.3 -> 2.13.4
-
#3929 From now,
SchemaIdvalue class is used in every place where schema id was represented as an Int. For conversion betweenSchemaIdandIntuseSchemaId.fromIntandSchemaId.asInt. UseConfluentUtils.toSchemaWithMetadatainstead ofSchemaWithMetadata.applyfor conversion between Confluent'sSchemaMetadataand oursSchemaWithMetadata. -
#3948 Now, we are less dependent from Confluent schema registry. To make it possible, some kafka universal/avro components refactors were done. Most important changes in public API:
- ConfluentSchemaBasedSerdeProvider.universal was replaced by UniversalSchemaBasedSerdeProvider.create
Some other, internal changes:
- Non-confluent classes renamed and moved to desired packages
- Extracted new class: SchemaIdFromMessageExtractor to make Confluent logic explicit and moved to top level
- Extracted SchemaValidator to make Confluent logic explicit and be able to compose
- Some renames: ConsumerRecordUtils -> KafkaRecordUtils
- RecordDeserializer -> AvroRecordDeserializer (also inheritance replaced by composition)
- (De)SerializerFactory - easier abstractions
- ConfluentSchemaRegistryFactory is not necessary now - removed
In version 1.7.0
Scenario authoring changes
- #3701 Right now access in SpEL to not existing field on TypedMap won't throw exception, just will return
null - #3727 Improvements: Change RR Sink validation way:
- Added param
Value validation modeat RR response component - We no longer support
nullableparam from Everit schema. Nullable schema are supported by union with null e.g. `["null", "string"]
- Added param
Configuration changes
- #3768
request-response-embeddedandstreaming-lite-embeddedDeploymentManager types where replaced by onelite-embeddedDeploymentManager type with two modes:streamingandrequest-responselike it is done inlite-k8scase
Code API changes
- #3560, #3595
Remove dependency on
flink-scala. In particular:- Switched from using
scala.DataStreamtodatastream.DataStream. Some tools exclusive to scala datastreams are available inengine.flink.api.datastream - Scala based
TypeInformationderivation is no longer used, for remaining casesflink-scala-utilsmodule is provided (probably will be removed in the future)
- Switched from using
- #3680
SubprocessRef::outputVariableNamestype is changed fromOption[Map[String,String]]with default None, toMap[String,String]with defaultMap.empty - #3692 Rename
mockedResulttoexternalInvocationin test results collectors. - #3606 Removed nussknacker-request-response-app. As a replacement you can use:
- nussknacker-request-response-app in version <= 1.6
- Lite K8s engine with request-response processing mode
lite-embeddedDeployment Manager with request-response processing mode
- #3610 Removed deprecated code. For details see changes in pull request.
- #3607 Request-response jsonSchema based encoder:
- ValidationMode moved to package
pl.touk.nussknacker.engine.api.validationinnussknacker-components-api - BestEffortJsonSchemaEncoder moved to package
pl.touk.nussknacker.engine.json.encodeinnussknacker-json-utils
- ValidationMode moved to package
- #3738 Kafka client libraries upgraded to 3.2.3. If using older Flink version, make sure to use 2.8.x client libraries. For Flink versions 1.15.0-1.15.2 include also fixed KafkaMetricWrapper
- #3668 Method
runWithRequestsofRequestResponseTestScenarioRunner(returned byTestScenarioRunner.requestResponseBased()) now returnsValidatedNelwith scenario compilation errors instead of throwing exception in that case
REST API changes
- #3576
/processesendpoint without query parameters returns all scenarios - the previous behaviour was to return only unarchived ones. To fetch only unarchived scenariosisArchived=falsequery parameter has to be passed.
Other changes
- #3824 Due to data serialization fix, Flink scenarios using Kafka sources with schemas may be incompatible and may need to be restarted with clean state.
In version 1.6.0
- #3440 Feature: allow to define fragment's outputs
- Right now using fragments in scenario is changed. We have to provide each outputName for outputs defined in fragment.
Scenario authoring changes
- #3370 Feature: scenario node category verification on validation From now import scenario with nodes from other categories than scenario category will be not allowed.
- #3436 Division by zero will cause validation error. Tests that rely on
1/0to generate exceptions should have it changed to code like1/{0, 1}[0] - #3473 JsonRequestResponseSinkFactory provides also 'raw editor', to turn on 'raw editor' add
SinkRawEditorParamName -> "true" - #3608 Use
ZonedDateTimefordate-timeJsonSchema format,OffsetTimefortimeformat.
Code API changes
- #3406 Migration from Scalatest 3.0.8 to Scalatest 3.2.10 - if necessary, see the Scalatest migration guides, https://www.scalatest.org/release_notes/3.1.0 and https://www.scalatest.org/release_notes/3.2.0
- #3431 Renamed
helper-utilstodefault-helpers, separatedMathUtilsfromcomponents-utilstomath-utils, removed dependencies fromhelper-utils - #3420
DeploymentManagerProvider.typeSpecificInitialDatatakes deploymentConfigConfignow - #3493, #3582 Added methods
DeploymentManagerProvider.additionalPropertiesConfig,DeploymentManagerProvider.additionalValidators - #3506 Changed
LocalDateTimetoInstantinOnDeployActionSuccessinlistener-api - #3513 Replace
EspProcesswithCanonicalProcessin all parts of the API except for the compiler. - #3545
TestScenarioRunner.flinkBasedshould be used instead ofNuTestScenarioRunner.flinkBased. Before this, you need toimport pl.touk.nussknacker.engine.flink.util.test.FlinkTestScenarioRunner._ - #3386 Changed
CustomProcessValidatorvalidatemethod. It now receivesCanonicalProcessinstead ofDisplayableProcessand returnsValidatedNel[ProcessCompilationError, Unit]instead ofValidationResult. MovedCustomProcessValidatorfrom modulenussknacker-restmodelin packagevalidationtonussknacker-extensions-api. - #3586 Module
nussknacker-uiwas renamed tonussknacker-designer,ui.confwas renamed todesigner.conf,defaultUiConfing.confrenamed todefaultDesignerConfig.conf
REST API changes
- #3506 Dates returned by REST API (createdAt, modifiedAt, createDate) are now returned in Zulu time, with timezone indication. This affects e.g.
/api/procecesses,/api/processes/{scenarioId},/api/processes/{scenarioId}/activity - #3542 Node additional info path renamed from
nodes/{scenarioId}/additionalDatatonodes/{scenarioId}/additionalInfo
Scenario API changes
- #3471, #3553
RequestResponseMetaData(path)is changed toRequestResponseMetaData(slug).V1_033__RequestResponseUrlToSlugmigration is ready for that, the change also applies to Scenario DSL. - #3513 Scenario DSL returns
CanonicalProcessinstead ofEspProcess. - #3630
SubprocessOutputchanged toSubprocessUsageOutput, changes inOutputVardefinition
Configuration changes
- #3425 Deployment Manager for
request-response-embeddedconfiguration parameters changed:interface->http.interfaceport->http.portdefinitionMetadata->request-response.definitionMetadata
- #3502 Refactor of
KafkaProperties:kafkaAddressproperty has been deprecated. Please providekafkaProperties."bootstrap.servers"instead
Other changes
- #3441 Updated Flink 1.14.5 -> 1.15.2. Some Flink artefacts no longer have Scala version. Test using Flink may need to disable checkpointing or reduce time between checkpoints to prevent timeouts or long waits for tasks to finish.
In version 1.5.0
Configuration changes
- #2992 deploySettings changed to deploymentCommentSettings, now when specified require you to also specify field validationPattern, specifying exampleComment is optional.
- commentSettings fields modified. matchExpression changed to substitutionPattern, link changed to substitutionLink.
- #3165 Config is not exposed over http (GET /api/app/config/) by default. To enable it set configuration
enableConfigEndpointtotrue. - #3223 OAuth2 configuration
defaultTokenExpirationTimechanged todefaultTokenExpirationDuration - #3263 Batch periodic scenarios carry processing type to distinguish scenarios with different categories.
For existing scenarios processing type is migrated to
default. SetdeploymentManager.processingTypetodefaultor update periodic scenarios table with actual processing type value - ideally it should be same value as the periodic engine key inscenarioTypes.
Code API changes
- #2992 OnDeployActionSuccess in ProcessChangeEvent now requires instance of Option[Comment] instead of Option[String] as parameter with deploymentComment information. Added abstract class Comment in listener-api.
- #3136 Improvements: Lite Kafka testkit
ConfluentUtils.serializeRecordToBytesArrayreplaced byConfluentUtils.serializeDataToBytesArrayConfluentUtils.deserializeSchemaIdAndRecordreplaced byConfluentUtils.deserializeSchemaIdAndData
- #3178 Improvements: more complex test scenario runner result:
- Right now each method from
TestScenarioRunnershould returnValidatedNel[ProcessCompilationError, RunResult[R]]where:- Invalid is representation of process compilation errors
- Valid is representation of positive and negative scenario running result
- Right now each method from
- #3255
TestReporterutil class is safer to use in parallel tests, methods require passing scenario name - #3265 #3288 #3297 #3299#3309
#3316 #3322 #3328 #3330 Changes related with UniversalKafkaSource/Sink:
RuntimeSchemaDatais generic - parametrized byParsedSchema(AvroSchema and JsonSchema is supported).NkSerializableAvroSchemarenamed toNkSerializableParsedSchemaSchemaWithMetadatawrapsParsedSchemainstead of AvroSchema.SchemaRegistryProviderrefactoring:- rename
SchemaRegistryProvidertoSchemaBasedSerdeProvider - decouple
SchemaRegistryClientFactoryfromSchemaBasedSerdeProvider
- rename
KafkaAvroKeyValueDeserializationSchemaFactoryrenamed toKafkaSchemaBasedKeyValueDeserializationSchemaFactoryKafkaAvroValueSerializationSchemaFactoryrenamed toKafkaSchemaBasedValueSerializationSchemaFactoryKafkaAvroKeyValueSerializationSchemaFactoryrenamed toKafkaSchemaBasedKeyValueSerializationSchemaFactory
- #3253
DeploymentManagerhas separatevalidatemethod, which should perform initial scenario validation and return reasonably quickly (while deploy can e.g. make Flink savepoint etc.) - #3313 Generic types handling changes:
Typed.typedClass(Class[_], List[TypingResult])is not available anymore. You should use more explicitTyped.genericTypeClassinstead- We check count of generic parameters in
Typed.genericTypeClass- wrong number will cause throwing exception now - We populate generic parameters by correct number of
Unknownin non-generic aware versions ofTypedfactory methods likeTyped.applyorTyped.typedClass
- #3071 More strict Avro schema validation:
ValidationMode.allowOptionalwas removed, instead of it please useValidationMode.laxValidationMode.allowRedundantAndOptionalwas removed, instead of it please useValidationMode.lax- Changes of
ValidationMode, fields:acceptUnfilledOptionalandacceptRedundantwere removed
- #3376
FlinkKafkaSource.flinkSourceFunction,FlinkKafkaSource.createFlinkSourceandDelayedFlinkKafkaConsumer.applytakes additional argument,FlinkCustomNodeContextnow - #3272
KafkaZookeeperServerrenamed toEmbeddedKafkaServer,zooKeeperServerfield changed type toOptionand is hidden now. - #3365 Numerous renames:
- module
nussknacker-avro-components-utils->nussknacker-schemed-kafka-components-utils - module
nussknacker-flink-avro-components-utils->nussknacker-flink-schemed-kafka-components-utils - package
pl.touk.nussknacker.engine.avro->pl.touk.nussknacker.engine.schemedkafka - object
KafkaAvroBaseComponentTransformer->KafkaUniversalComponentTransformer
- module
- #3412 More strict filtering method types. Methods with parameters or result like
Collection[IllegalType]are no longer available in SpEl. - #3542 Numerous renames:
- trait
NodeAdditionalInfo->AdditionalInfo, - class
MarkdownNodeAdditionalInfo->MarkdownAdditionalInfo - trait
NodeAdditionalInfoProvider->AdditionalInfoProvider- the SPI provider's configuration files must be renamed frompl.touk.nussknacker.engine.additionalInfo.NodeAdditionalInfoProvidertopl.touk.nussknacker.engine.additionalInfo.AdditionalInfoProvider - method
AdditionalInfoProvider.additionalInforenamed tonodeAdditionalInfoand new method addedpropertiesAdditionalInfo
- trait
REST API changes
- #3169 API endpoint
/api/app/healthCheckreturning short JSON answer with "OK" status is now not secured - before change it required to be an authenticated user with "read" permission.
Scenario authoring changes
- #3187 #3224 Choice component replaces Switch component. "Default" choice edge type, exprVal and expression are now deprecated. For existing usages, you don't need to change anything. For new usages, if you want extract value e.g. to simplify choice conditions, you need to define new local variable before choice using variable component. "Default" choice edge type can be replaced by adding "true" condition at the end of list of conditions
Breaking changes
- #3328 Due to addition of support for different schema type (AvroSchema and JsonSchema for now) serialization format of
NkSerializableParsedSchemahas changed. Flink state compatibility of scenarios which use Avro sources or sinks has been broken. - #3365 Due to renames (see section
Code API changes) Flink state compatibility of scenarios which use Avro sources or sinks has been broken.
Other changes
- #3249#3250 Some kafka related libraries were bumped: Confluent 5.5->7.2, avro 1.9->1.11, kafka 2.4 -> 3.2.
It may have influence on your custom components if you depend on
kafka-components-utilsoravro-components-utilsmodule - #3376 Behavior of Flink's Kafka deserialization errors handling was changed - now instead of job failure, invalid message is omitted and configured
exceptionHandlermechanism is used.
In version 1.4.0
Configuration changes
security.rolesClaimchanged tosecurity.rolesClaims, type changed to list of stringskafka.schemaRegistryCacheConfigconfiguration entry was added - it was hardcoded before. Default value ofkafka.schemaRegistryCacheConfig.availableSchemasExpirationTimewas changed from 1 minute to 10 seconds which will cause more often schema cache invalidation- #3031 Attachments are now stored in database (see more in section
Other changes).attachmentsPathwas removed. Optional configattachments.maxSizeInByteswas introduced with default value of 10mb
Code API changes
- #2983 Extract Permission to extensions-api
- Moved
pl.touk.nussknacker.ui.security.api.Permission(security module) topl.touk.nussknacker.security.Permission(extension-api module)
- Moved
- #3040 Deprecated
pl.touk.nussknacker.engine.api.ProcessListener.sinkInvokedmethod. Switch to more generalendEncounteredmethod. - #3076 new implicit parameter
componentUseCase: ComponentUseCasewas added toinvoke()method of all services extendingEagerServiceWithStaticParameters
Other changes
- #3031 Attachments are now stored in database. As this feature was rarely used, automatic migration of attachments from disk to db is not provided. To stay consistent db table
process_attachmentshad to be truncated.
Breaking changes
- #3029
KafkaConfighas new fieldschemaRegistryCacheConfig: SchemaRegistryCacheConfig. Flink state compatibility has been broken. - #3116 Refactor
SchemaRegistryClientFactoryso it takes dedicated config object instead of KafkaConfig. This change minimizes chance of future Flink state compatibility break.SchemaIdBasedAvroGenericRecordSerializeris serialized in Flink state, so we provide it now with as little dependencies as necessary. Flink state compatibility has been broken again. - #3363 Kafka consumer no longer set
auto.offset.resettoearliestby default. For default configuration files, you can useKAFKA_AUTO_OFFSET_RESETenv variable to easily change this setting.
In version 1.3.0
Code API changes
- #2741 #2841 Remove custom scenario provides some changes on API:
- Replace ProcessDeploymentData by CanonicalProcess (as VO)
- Replace scenario jsonString by CanonicalProcess at DeploymentManager, ProcessConfigEnricherInputData
- #2773 Using VersionId / ProcessId / ProcessName instead of Long or String:
PullProcessRepositoryAPI was changed, right now we use VersionId instead of Long
- #2830
RunModeis renamed toComponanteUseCaseandNormalvalue is split into: EngineRuntime, Validation, ServiceQuery, TestDataGeneration.RunMode.TestbecomesComponanteUseCase.TestRuntime - #2825, #2868 #2912 API modules changes:
- Extracted new modules:
nussknacker-scenario-apiwith all scenario API parts fromapiandinterpreternussknacker-components-api(andnussknacker-lite-components-api,nussknacker-flink-components-apietc.), which contain API for creating componentsnussknacker-common-api- base value classes shared betweenscenario-apiandcomponents-apilikeNodeId,Metadataetc.nussknacker-extensions-api- API of extensions other than components
- Because of that, some changes in code were also introduced:
NodeIdmoved frompl.touk.nussknacker.engine.api.context.ProcessCompilationErrortopl.touk.nussknacker.engine.apiNodeExpressionId,DefaultExpressionIdandbranchParameterExpressionIdmoved frompl.touk.nussknacker.engine.api.context.ProcessCompilationErrortopl.touk.nussknacker.engine.graph.expressionJobDatano longer containsDeploymentData, which is not accessible for components anymoreDisplayJson,WithJobData,MultiMapmoved toutils- Some methods from API classes (e.g.
Parameter.validate) and classes (InterpretationResult) moved to interpreter DeploymentManagerProvider.createDeploymentManagertakes nowBaseModelDataas an argument instead ofModelData. If you want to use this data to invoke scenario, you should cast it to invokable representation via:import ModelData._; modelData.asInvokableModelData
- Extracted new modules:
- #2878 #2898 #2924 Cleaning up of
-utilsmodules- Extracted internal classes, not intended to be used in extensions to nussknacker-internal-utils module
- Extracted component classes, not used directly by runtime/designer to nussknacker-components-utils module
- Extracted kafka component classes, not used directly by lite-kafka-runtime/kafka-test-utils to nussknacker-kafka-components-utils
- Moved some classes that are in fact part of API to -api modules (e.g.
ToJsonEncoder) - Module renames:
- nussknacker-avro-util to nussknacker-avro-components-utils
- nussknacker-flink-avro-util to nussknacker-flink-avro-components-utils
- nussknacker-flink-kafka-util to nussknacker-flink-kafka-components-utils
- nussknacker-flink-util to nussknacker-flink-components-utils
- nussknacker-request-response-util to nussknacker-request-response-components-utils
- nussknacker-model-util to nussknacker-helpers-utils
- Minor changes in code:
- Use
val docsConfig = new DocsConfig(config); import docsConfig._instead ofimplicit val docsConfig = (...); import DocsConfig._ - Some components specific methods are not available from
KafkaUtils. Instead, they are available fromKafkaComponentsUtils ToJsonEncoder.encodertakesAny => Jsonfunction instead ofBestEffortJsonEncoderas a parameter
- Use
- #2907 Hide some details of metrics to
utils-internal(InstantRateMeter,InstantRateMeterWithCount), use method added toMetricsProviderForScenario - #2916 Changes in
ProcessStateAPI.- Six similar methods creating
ProcessStatebased onStateStatusand some other details merged to one.- Methods removed:
- Two variants of
ProcessState.applytakingProcessStateDefinitionManageras a parameter SimpleProcessState.apply- Two variants of
ProcessStatus.simple ProcessStatus.createStatetakingProcessStateDefinitionManageras a parameter
- Two variants of
- Method added:
ProcessStateDefinitionManager.processStatewith some default parameter values
- Methods removed:
ProcessStatusclass is removed at all. All methods returningProcessStateby it moved toSimpleProcessStateDefinitionManagerand removedpreviousState: Option[ProcessState]from it. If you want to keep previous state's deployment details and only change "status details" just useprocessState.withStatusDetailsmethodProcessState,CustomActionand its dependencies moved fromnussknacker-deployment-manager-apitonussknacker-scenario-deployment-api,restmodelmodule not depend ondeployment-manager-apianymore- #2969 Action
ProcessActionType.Deployis now available by default for scenarios inSimpleStateStatus.DuringDeploystate. Mind this if you depend onOverridingProcessStateDefinitionManagerorSimpleProcessStateDefinitionManager, and specifically on theirsstatusActionsmethod. As an exception, implementation for FlinkFlinkProcessStateDefinitionManagerstays the same as before (onlyProcessActionType.Cancelis possible in this state), but this may be unified in the future.
- Six similar methods creating
Other changes
- #2886 This change can break previous flink snapshot compatibility. Restoring state from previous snapshot asserts that restored serializer UID matches current serializer UID. This change ensures that in further release deployments UIDs persisted within snapshots are not re-generated in runtime.
- #2950 Remove
MATHhelper, useNUMERICmethods (they work better with some number types conversions)
In version 1.2.0
Configuration changes
- #2483
COUNTS_URLenvironment variable is notINFLUXDB_URL, withoutquerypath part. - #2493 kafka configuration should be moved to components provider configuration - look at
components.kafkain dev-application.conf for example - #2624 Default name for
processtag is nowscenario. This affects metrics and count functionalities. Please update you Flink/Telegraf setup accordingly (see nussknacker-quickstart for details). If you still want to useprocesstag (e.g. you have a lot of dashboards), please setcountsSettings.metricsConfig.scenarioTagsetting toprocessAlso, dashboard links format changed, see documentation for the details. - #2645 Default models:
genericModel.jar,liteModel.jar. were merged todefaultModel.jar,managementSample.jarwas renamed todevModel.jar. If you usedefaultModel.jarit's important to includeflinkExecutor.jarexplicitly on model classpath.
Scenario authoring changes
- #2564 Flink union now takes only 'Output expression' parameters for branches (previously 'value' parameter), output variable must be of the same type, if you want to distinguish source branch in output variable please use map variable, example in Basic Nodes docs.
Other changes
- #2554 Maven artifact
nussknacker-kafka-flink-utilbecomenussknacker-flink-kafka-utilandnussknacker-avro-flink-utilbecomenussknacker-flink-avro-util. General naming convention isnussknacker-$runtimeType-$moduleName. Components inside distribution changed layout tocomponents(/$runtimeType)/componentName.jare.g.components/flink/kafka.jarorcomponents/openapi.jarKafkaSourcebecomeFlinkKafkaSource,ConsumerRecordBasedKafkaSourcebecomeFlinkConsumerRecordBasedKafkaSource,KafkaSinkbecomeFlinkKafkaSink,KafkaAvroSinkbecomeFlinkKafkaAvroSink - #2535, #2625, #2645 Rename
standalonetorequest-response:- Renamed modules and artifacts
StandaloneMetaDatais nowRequestResponseMetaData- Move
request-responsemodules tobasedir. standalonein package names changed torequestresponseStandalonein class/variable names changed toRequestResponseDeploymentManager/Serviceuses dedicated format of status DTO, instead of the ones fromdeployment-manager-api- Removed old, deprecated
jarPathsettings, in favour ofclassPathused in other places - Extracted
nussknacker-lite-request-response-componentsmodule
- #2582
KafkaUtils.toProducerPropertiessetup only basic properties now (bootstrap.serversand serializers) - before the change it was setting options which are not always good choice (for transactional producers wasn't) - #2600
ScenarioInterpreter,ScenarioInterpreterWithLifecyclenow takes additional generic parameter:Input.ScenarioInterpreter.invoketakesScenarioInputBatchwhich now contains list ofSourceId -> Inputinstead ofSourceId -> Context. Logic ofContextpreparation should be done inLiteSourceinstead of beforeScenarioInterpreter.invoke. invocation It means thatLiteSourcealso takes this parameter and have a new methodcreateTransformation. - #2635
ContextInitializer.initContextnow takesContextIdGeneratorinstead ofnodeIdand returns just a function with strategy of context initialization instead of serializable function withLifecycle. To use it with Flink engine, useFlinkContextInitializingFunctionwrapper. - #2649
DeploymentManagerProvidertakes newProcessingTypeDeploymentServiceclass as an implicit parameter - #2564 'UnionParametersMigration' available to migrate parameter name from 'value' to 'Output expression' - please turn it on you are using 'union' like component
- #2645 Simplify structure of available models (implementations of
ProcessConfigCreator).defaultModel.jarand components should be used instead of custom implementations ofProcessConfigCreator, the only exception is when one wants to customizeExpressionConfig. Also,nussknacker-flink-enginemodule becamenussknacker-flink-executor. - #2651
ValidationContext.clearVariablesnow clears also parent reference. Important when invoked inside fragments. - #2673
KafkaZookeeperUtilsrenamed toKafkaTestUtils, it doesn't depend on ZooKeeper anymore. - #2686
ServiceWithStaticParametersrenamed toEagerServiceWithStaticParameters. - #2695
nodeIdreplaced withNodeComponentInfoinNuExceptionInfo. Simple wrapper class which holds the samenodeIdand alsocomponentInfo. Migration is straightforward, just putnodeIdinto the new case class:NuExceptionInfo(None, exception, context)=> stays the sameNuExceptionInfo(Some(nodeId), exception, context)=>NuExceptionInfo(Some(NodeComponentInfo(nodeId, None)), exception, context)- if an exception is thrown inside the component, additional information can be provided:
- for base component (like
filterorsplit):NodeComponentInfo.forBaseNode("nodeId", ComponentType.Filter) - for other:
NodeComponentInfo("nodeId", ComponentInfo("kafka-avro-source", ComponentType.Source))
- for base component (like
- if an exception is thrown inside the component, additional information can be provided:
- The same migration has to be applied to
ExceptionHandler.handling()method.
- #2824 'ProcessSplitterMigration' available to migrate node name from 'split' to 'for-each' (see #2781)- please turn it on if you are using 'split' component
In version 1.1.0
Summary:
- A lot of internal refactoring was made to separate code/API specific for Flink.
If your deployment has custom components pay special attention to:
Lifecyclemanagement- Kafka components
- Differences in artifacts and packages
- Some of the core dependencies: cats, cats-effect and circe were upgraded. It affects mainly code, but it may also have impact on state compatibility and performance.
- Default Flink version was bumped do 1.14 - see https://github.com/TouK/nussknacker-flink-compatibility on how to run Nu on older Flink versions.
- Execution of SpEL expressions is now checked more strictly, due to security considerations. These checks can be overridden with custom
ExpressionConfig.
- Apart from that:
- minor configuration naming changes
- removal of a few of minor, not documented features (e.g. SQL Variable)
- #2208 Upgrade, cats, cats-effects, circe. An important nuisance: we didn't upgrade sttp, so we cannot depend on
"com.softwaremill.sttp.client" %% "circe". Instead, the code is copied. Make sure you don't include sttp-circe integration as transitive dependency, but use class from http-utils instead. - #2176
EnrichDeploymentWithJarDataFactorywas replaced withProcessConfigEnricher. - #2278 SQL Variable is removed
- #2280 Added optional
defaultValuefield toParameter. InGenericNodeTransformationcan be set toNone- values will be determined automatically. - #2289 Savepoint path in
/api/adminProcessManagement/deployendpoint is passed as asavepointPathparameter instead of path segment. - #2293 Enhancement: change
nodeCategoryMappingconfiguration tocomponentsGroupMapping - #2301 #2620
GenericNodeTransformation.initialParameterswas removed - nowGenericNodeTransformation.contextTransformationis used instead. To make Admin tab -> Invoke service form working, useWithLegacyStaticParameterstrait - #2409
JsonValidatoris now not determined by default based onJsonParameterEditorbut must be explicitly defined by@JsonValidatorannotation - #2304 Upgrade to Flink 1.14. Pay attention to Flink dependencies - in some (e.g. runtime) there is no longer scala version.
- #2295
FlinkLazyParameterFunctionHelperallows (and sometimes requires) correct exception handling - #2307 Changed
nussknacker-kafkamodule name tonussknacker-kafka-util - #2310 Changed
nussknacker-processmodule name tonussknacker-flink-engine - #2300 #2343 Enhancement: refactor and improvements at components group:
- Provided
ComponentGroupNameas VO SingleNodeConfigwas renamed toSingleComponentConfigand moved frompl.touk.nussknacker.engine.api.processpackage topl.touk.nussknacker.engine.api.component- Configuration
categoryin node configuration was replaced bycomponentGroup - Configuration
nodesin model configuration was replaced bycomponentsUiConfig - Additional refactor:
ProcessToolbarServicemoved frompl.touk.nussknacker.ui.servicepackage topl.touk.nussknacker.ui.process - Additional refactor:
ProcessToolbarServicemoved frompl.touk.nussknacker.ui.servicepackage topl.touk.nussknacker.ui.process DefinitionPreparerwas renamed toComponentDefinitionPreparerNodesConfigCombinerwas removed- REST API /api/processDefinitionData/* response JSON was changed:
nodesToAddwas renamed tocomponentGroupsposibleNodewas renamed tocomponentsnodesConfigwas renamed tocomponentsConfig- config
iconproperty fromcomponentsConfigright now should be relative tohttp.publicPathe.g./assets/components/Filter.svg(before was justFilter.svg) or url (withhttp/https)
- Provided
- #2346 Remove
endResultfromSinkin graph.Sinkno longer definestestOutputmethod - they should be handled by respective implementations- Change in definition of
StandaloneSinkpreviouslyStandaloneSinkWithParameters, as output always has to be computed with sink parameters now - Changes in definition of
FlinkSink, to better handle capturing test data - Removal of
.sinkmethod inGraphBuilder- use.emptySinkif suitable
- #2331
KafkaAvroBaseTransformercompanion object renamed toKafkaAvroBaseComponentTransformerKryoGenericRecordSchemaIdSerializationSupportrenamed toGenericRecordSchemaIdSerializationSupport
- #2305 Enhancement: change
processingTypeToDashboardconfiguration toscenarioTypeToDashboard - #2296 Scenarios & Fragments have separate TypeSpecificData implementations. Also, we remove
isSubprocessfield from process JSON, and respectively from MetaData constructor. See corresponding db migrationV1_031__FragmentSpecificData.scala - #2368
WithCategoriesnow takes categories as anOption[List[String]]instead ofList[String]. You should wrap given list of categories withSome(...).Nonemean that component will be available in all categories. - #2360
union,union-memoanddead-endcomponents were extracted frommodel/genericModel.jartocomponents/baseComponents.jarIf you have your ownapplication.confwhich changesscenarioTypes, you should add"components/baseComponents.jar"entry intoclassPatharray - #2337 Extract base engine from standalone
- Common functionality of base engine (i.e. microservice based, without Flink) is extracted to
base-apiandbase-runtime - new API for custom components (
pl.touk.nussknacker.engine.baseengine.api.customComponentTypes) StandaloneProcessInterpreterbecomesStandaloneScenarioEngine- Replace
Either[NonEmptyList[Error], _]withValidatedNel[Error, _]as return type StandaloneContextbecomesEngineRuntimeContext
- Common functionality of base engine (i.e. microservice based, without Flink) is extracted to
- #2349
queryable-statemodule was removed,FlinkQueryableClientwas moved tonussknacker-flink-manager.PrettyValidationErrors,CustomActionRequestandCustomActionResponsemoved fromnussknacker-uitonussknacker-restmodel. - #2361 Removed
securitydependency fromlistener-api.LoggedUserreplaced with dedicated class inlistener-api. - #2385 Deprecated
CustomStreamTransformer.clearsContextwas removed. Use
@MethodToInvoke
def execute(...) =
ContextTransformation
.definedBy(ctx => Valid(ctx.clearVariables ...))
.implementedBy(...)
}
instead.
- #2348 #2459 #2486
#2490 #2496 #2536
Introduce
KafkaDeserializationSchemaandKafkaSerializationSchematraits to decouple from flink dependency. moveKeyedValuetonussknacker-util, moveSchemaRegistryProvidertoutils/avro-utilTo move between nussknacker's/flink's Kafka(De)serializationSchema usewrapToFlink(De)serializatioinSchemafromFlinkSerializationSchemaConversions.SchemaRegistryProviderandConfluentSchemaRegistryProvideris now innussknacker-avro-utilmodule.FlinkSourceFactoryis gone - useSourceFactoryinstead.KafkaSourceFactory,KafkaAvroSourceFactory,KafkaSinkFactory,KafkaAvroSinkFactory, andContextIdGeneratornot depends on flink. ExtractedKafkaSourceImplFactory,KafkaSinkImplFactoryandKafkaAvroSinkImplFactorywhich deliver implementation of component (after all validations and parameters evaluation). Use respectively:FlinkKafkaSourceImplFactory,FlinkKafkaSinkImplFactoryandFlinkKafkaAvroSinkImplFactoryto deliver flink implementations. Moved non-flink specific serializers, deserializers,BestEffortAvroEncoder,ContextIdGenerators andRecordFormatters to kafka-util/avro-utilKafkaDelayedSourceFactoryis nowDelayedKafkaSourceFactory.FixedRecordFormatterFactoryWrappermoved toRecordFormatterFactory - #2477
FlinkContextInitializerandFlinkGenericContextInitializermerged toContextInitializer,BasicFlinkContextInitializerandBasicFlinkGenericContextInitializermerged toBasicContextInitializer. All of them moved topl.touk.nussknacker.engine.api.processpackage.ContextInitializer.validationContextreturnsValidatedNel- before this change errors during context initialization weren't accumulated.ContextInitializingFunctionnow is a scala's function instead of Flink's MapFunction. You should wrap it withRichLifecycleMapFunctionto make sure that it will be opened correctly by Flink.InputMetawas moved tokafka-utilmodule. - #2389 #2391
deployment-manager-apimodule was extracted andDeploymentManagerProvider,ProcessingTypeDataandQueryableClientwas moved frominterpreterinto it.DeploymentManager,CustomActionandProcessStatewas moved fromapitodeployment-manager-api.ProcessingTypewas moved torest-modelpackage. - #2393 Added
ActorSystem,ExecutionContextandSttpBackendintoDeploymentManagerProvider.createDeploymentManager. During clean ups also was removednussknacker-http-utilsdependency toasync-http-client-backend-futureand addedSttpBackendtoCountsReporterCreator.createReporterarguments. - #2397 Common
EngineRuntimeContextlifecycle andMetricsProvider. This may cause runtime consequences - make sure your custom services/listeners invokeopen/closecorrectly - especially in complex inheritance scenarios.Lifecyclehas nowEngineRuntimeContextas parameter,JobDatais embedded in it.TimeMeasuringServicereplacesGenericTimeMeasuringService, Flink/Standalone flavours ofTimeMeasuringServiceare removedEngineRuntimeContextandMetricsProvidermoved to base API,RuntimeContextLifecyclemoved to base API asLifecycleGenericInstantRateMeteris nowInstantRateMeter- Flink
RuntimeContextLifecycleshould be replaced in most cases byLifecycle - In Flink engine
MetricsProvider(obtained withEngineRuntimeContext) should be used in most places instead ofMetricUtils
- #2486
Context.withInitialIdis deprecated now - useEngineRuntimeContext.contextIdGeneratorinstead.EngineRuntimeContextcan be accessible viaFlinkCustomNodeContext.convertToEngineRuntimeContext - #2377 #2534 Removed
clazzfromSourceFactory. Remove generic parameter fromSourceandSourceFactory. Return type of source should be returned either by:returnTypefield of@MethodToInvokeContextTransformationAPIGenericNodeTransformerAPISourceFactory.noParam
- #2453 Custom actions for
PeriodicDeploymentManagernow can be defined and implemented outside this class, inPeriodicCustomActionsProvidercreated byPeriodicCustomActionsProviderFactory. If you do not need them, just passPeriodicCustomActionsProviderFactory.noOpto object'sPeriodicDeploymentManagerfactory method. - #2501
nussknacker-baseengine-componentsmodule renamed tonussknacker-lite-base-components - #2221 ReflectUtils
fixedClassSimpleNameWithoutParentModulerenamed tosimpleNameWithoutSuffix - #2495 TypeSpecificDataInitializer trait change to TypeSpecificDataInitializ
- #2245
FailedEventhas been specified inFailedOnDeployEventandFailedOnRunEvent
In version 1.0.0
- #1439 #2090 Upgrade do Flink 1.13.
setTimeCharacteristicis deprecated, and should be handled automatically by Flink.UserClassLoaderwas removed, use appropriate Flink objects or context ClassLoader.- RocksDB configuration is turned on by
rocksdb.enableinstead ofrocksdb.checkpointDataUriwhich is not used now.
- #2133 SQL Variable is hidden in generic model, please look at comment in
defaultModelConfig.conf - #2152
schedulePropertyExtractorparameter ofPeriodicDeploymentManagerProviderwas changed to a factory, replace with a lambda creating the original property extractor. - #2159
useTypingResultTypeInformationoption is now enabled by default - #2108 Changes in
ClassExtractionSettings:- Refactor of classes defining extraction rules,
TypedClasshas privateapplymethod, please useTyped.typedClass- Fewer classes/methods are accessible in SpEL, in particular Scala collections, internal time API, methods returning or having parameters from excluded classes
- Changes in
OAuth2security components:- refactoring of
OpenIdConnectService, now it's namedGenericOidcService(it's best to useOidcService, which can handle most of the configuration automatically)
- refactoring of
- New security settings, in particular new flags in
ExpressionConfig:strictMethodsCheckingstaticMethodInvocationsCheckingmethodExecutionForUnknownAlloweddynamicPropertyAccessAllowedspelExpressionExcludeList
- #2101 Global permissions can be arbitrary string, for admin user it's not necessary to return global permissions
- #2182 To avoid classloader leaks during SQL
DriverManagerregistration, HSQLDB (used e.g. for SQL Variable) is no longer included in model jars, it should be added in Flinklibdir
In version 0.4.0
-
#1479
ProcessIdandVersionIdmoved to API included inProcessVersion, remove spuriousProcessIdandProcessVersionIdin restmodel. -
#1422 Removed
ServiceReturningTypeandWithExplicitMethod, useEagerServiceWithStaticParameters,EnricherContextTransformationorSingleInputGenericNodeTransformation -
#1845
AuthenticatorDatahas been renamed toAuthenticationResourcesand changed into a trait,applyconstruction has been preserved.AuthenticatorFactoryand itscreateAuthenticatormethod has been renamed toAuthenticationProviderandcreateAuthenticationResources. It is recommended to rename the main class of any custom authentication module to<Something>AuthenticationProvideraccordingly. -
#1542
KafkaConfignow has new parametertopicsExistenceValidationConfig. WhentopicsExistenceValidationConfig.enabled = trueKafka sources/sinks do not validate if provided topic does not exist and cluster is configured withauto.create.topics.enable=false -
#1416
OAuth2Servicehas changed. You can still use your old implementation by importingOAuth2OldServicewith an alias.OAuth2ServiceFactory.createmethod now accepts implicit parameters for anExecutionContextandsttp.HttpBackend. You can ignore them to maintain previous behaviour, but it is always better to use them instead of locally defined ones. -
#1346
AggregatorFunctionnow takes type of stored state that can beimmutable.SortedMap(previous behaviour) orjava.util.Map(using Flink's serialization) andvalidatedStoredTypeparameter for providing betterTypeInformationfor aggregated values -
#1343
FirstAggregatorchanged serialized state, it is not compatible,Aggregatortrait has new methodcomputeStoredType -
#1352 and #1568 AvroStringSettings class has been introduced, which allows control whether Avro type
stringis represented byjava.lang.String(also in runtime) orjava.lang.CharSequence(implemented in runtime byorg.apache.avro.util.Utf8). This setting is available through environment variableAVRO_USE_STRING_FOR_STRING_TYPE- default istrue. Please mind that this setting is global - it applies to all processes running on Flink and also requires restarting TaskManager when changing the value. -
#1361 Lazy variables are removed, you should use standard enrichers for those cases. Their handling has been source of many problems and they made it harder to reason about the exeuction of process.
-
#1373 Creating
ClassLoaderModelDatadirectly is not allowed, useModelData.applywith plain config, wrapping with ModelConfigToLoad by yourself is not needed. -
#1406
ServiceReturningTypeis deprecated in favour ofEagerService -
#1445
RecordFormatternow handlesTestDataSplitfor Kafka sources. It is required inKafkaSourcecreation, instead ofTestDataSplit -
#1433 Pass DeploymentData to process via JobData, additional parameters to deployment methods are needed. Separate
ExternalDeploymentIdfromDeploymentId(generated by NK) -
#1466
ProcessManager.deploycan returnExternalDeploymentId -
- Slight change of API of
StringKeyedValueMapper - Change of semantics of some parameters of
AggregatorFunction,AggregatorFunctionMixin(storedAggregateType becomes aggregateElementType)
- Slight change of API of
-
#1405 'KafkaAvroSink' requires more generic 'AvroSinkValue' as value parameter
-
- Change of
FlinkSourceAPI: sourceStream produces stream of initializedContext(DataStream[Context]) This initialization step was previously performed withinFlinkProcessRegistrar.registerSourcePart. Now it happens explicitly within the flink source. FlinkIntermediateRawSourceis used as an extension to flink sources, it prepares source with typical stream transformations (add source function, set uid, assign timestamp, initializeContext)FlinkContextInitializeris used to initializeContext. It provides map function that transforms raw event (produced by flink source function) intoContextvariable. Default implementation ofFlinkContextInitializer, seeBasicFlinkContextInitializer, sets raw event value to singe "input" variable.- For sources based on
GenericNodeTransformationit allows to initializeContextwith more than one variable. Default implementation of initializer, seeBasicFlinkGenericContextInitializer, provides default definition of variables as aValidationContextwith single "input" variable. The implementation requires to provide separately the definition of "input" variable type (TypingResult). SeeGenericSourceWithCustomVariablesSample. - To enable "test source" functionality, a source needs to be extended with
SourceTestSupport. - For flink sources that use
TestDataParserProviderswitch toFlinkSourceTestSupport(which is used to provide "test source" functionality for flink sources). - Old
TestDataParserProvideris renamed toSourceTestSupport - To enable test data generator for "test source" , a source needs to be extended with both
SourceTestSupportandTestDataGenerator. What was related to "test source" functionality and was obsolete inFlinkSourcenow is excluded toFlinkSourceTestSupport. FlinkCustomNodeContexthas access toTypeInformationDetection, it allows to get TypeInformation for the node stream mapping from ValidationContext.- For kafka sources
RecordFormatterparses raw test data toConsumerRecordwhich fits into deserializer (instead ofProducerRecordthat required another transformation). - Definitions of names of common
Contextvariables are moved toVariableConstants(instead ofInterpreter).
- Change of
-
#1497 Changes in
PeriodicProcessManager, changePeriodicPropertytoScheduleProperty -
- trait
KafkaAvroDeserializationSchemaFactoryuses both key and value ClassTags and schemas (instead of value-only), check the order of parameters. - ClassTag is provided in params in avro key-value deserialization schema factory:
KafkaAvroKeyValueDeserializationSchemaFactory BaseKafkaAvroSourceFactoryis able to read both key and value schema determiner to build proper DeserializationSchema (support for keys is not fully introduced in this change)
- trait
-
#1514
ExecutionConfigPreparerhas different method parameter -JobData, which has more info than previous parameters -
#1532
TypedObjectTypingResult#fieldsuses nowscala.collection.immutable.ListMapto keep fields order -
#1546
StandaloneCustomTransformernow takes a list ofContextobjects, to process them in one go -
#1557 Some classes from standalone engine were moved to standalone api to remove engine to (model) utils dependency:
StandaloneContext,StandaloneContextLifecycle,MetricsProvider -
#1558
FlinkProcessRegistrartakes configuration directly fromFlinkProcessCompiler(this can affect some tests setup) -
#1631 Introduction of
nussknacker.config.locationsproperty, drop use of standardconfig.fileproperty. Model configuration no longer has direct access to root UI config. -
- Replaced
KafkaSourceFactorywith source based onGenericNodeTransformation, which gives access to setup ofValidationContextandContextinitialization. To migrateKafkaSourceFactory:- provide deserializer factory (source factory requires deserialization to
ConsumerRecord):- use
ConsumerRecordDeserializationSchemaFactorywith currentDeserializationSchemaas a value deserializer, add key deserializer (e.g. org.apache.kafka.common.serialization.StringDeserializer) - or use
FixedValueDeserializationSchemaFactorywith simple key-as-string deserializer
- use
- provide RecordFormatterFactory
- use
ConsumerRecordToJsonFormatterFactoryfor whole key-value-and-metadata serialization - or, for value-only-and-without-metadata scenario, you can use current
RecordFormaterwrapped inFixedRecordFormatterFactoryWrapper
- use
- provide timestampAssigner that is able to extract time from
ConsumerRecord[K, V]
- provide deserializer factory (source factory requires deserialization to
- Removed
BaseKafkaSourceFactorywith multiple topics support: useKafkaSourceFactoryinstead, see "source with two input topics" test case - Removed
SingleTopicKafkaSourceFactory: useKafkaSourceFactorywith customprepareInitialParameters,contextTransformationandextractTopicsto alter parameter list and provide constant topic value. TypingResultAwareTypeInformationCustomisationis moved to package pl.touk.nussknacker.engine.flink.api.typeinformation
Example of source with value-only deserialization and custom timestampAssigner:
// provide new deserializer factory with old schema definition for event's value
val oldSchema = new EspDeserializationSchema[SampleValue](bytes => io.circe.parser.decode[SampleValue](new String(bytes)).toOption.get)
val schemaFactory: KafkaDeserializationSchemaFactory[ConsumerRecord[String, SampleValue]] = new FixedValueDeserializationSchemaFactory(oldSchema)
// ... provide timestampAssigner that extracts timestamp from SampleValue.customTimestampField
// ... or use event's metadata: record.timestamp()
def timestampExtractor(record: ConsumerRecord[String, SampleValue]): Long = record.value().customTimestampField
val watermarkHandler = StandardTimestampWatermarkHandler.boundedOutOfOrderness[ConsumerRecord[String, SampleValue]](timestampExtractor, java.time.Duration.ofMinutes(10L))
val timestampAssigner: Option[TimestampWatermarkHandler[ConsumerRecord[String, SampleValue]]] = Some(watermarkHandler)
// ... provide RecordFormatterFactory that allows to generate and parse test data with key, headers and other metadata
val formatterFactory: RecordFormatterFactory = new ConsumerRecordToJsonFormatterFactory[String, SampleValue]
// ... and finally
val sourceFactory = new KafkaSourceFactory[String, SampleValue](schemaFactory, timestampAssigner, formatterFactory, dummyProcessObjectDependencies) - Replaced
-
#1651
KafkaAvroSourceFactoryprovides additional #inputMeta variable with event's metadata.- That source now has key and value type parameters. That parameters are relevant for sources handling
SpecificRecords. ForGenericRecordsuse explicitlyKafkaAvroSourceFactory[Any, Any]. SpecificRecordKafkaAvroSourceFactoryextends wholeKafkaAvroSourceFactorywith context validation and initialization- New flag in
KafkaConfig:useStringForKeydetermines if event's key should be intepreted as ordinary String (which is default scenario). It is used in deserialization and for generating/parsing test data. SchemaRegistryProvidernow provides factories to produce SchemaRegistryClient and RecordFormatter.- For
ConfluentSchemaRegistryProviderKafkaConfig and ProcessObjectDependencies (that contains KafkaConfig data) are no longer required. That configuration is required by factories in the moment the creation of requested objects that happens inKafkaAvroSourceFactory(and that makes that all objects withinKafkaAvroSourceFactorysee the same kafka configuration). - Removed:
BaseKafkaAvroSourceFactory, the class is incorporated intoKafkaAvroSourceFactoryto provide elastic approach to create KafkaSourcewith ReturningTypefor generic types (this is defined by ValidationContext, see alsoKafkaContextInitializerthat allows to return more than one variable)KafkaAvroValueDeserializationSchemaFactory(source requires deserialization toConsumerRecord[K, V], there are only deserializers based onKafkaAvroKeyValueDeserializationSchemaFactory)ConfluentKafkaAvroDeserializationSchemaFactory, useConfluentKeyValueKafkaAvroDeserializationFactoryTupleAvroKeyValueKafkaAvroDeserializerSchemaFactory, this approach is deprecated due to #inputMeta variable that contains key data
To migrate
KafkaAvroSourceFactory:- Provide
KafkaConfigwith correctuseStringForKeyflag value. By default we want to EvictableStatehandle keys as ordinary String and all topics related to such config require only value schema definitions (key schemas are ignored). For specific scenario, when complex key with its own schema is provided, this flag is false and all topics related to this config require both key and value schema definitions. Example of default KafkaConfig override:override protected def prepareKafkaConfig: KafkaConfig = super.prepareKafkaConfig.copy(useStringForKey = false) - provide your own
SchemaRegistryProvider(or useConfluentSchemaRegistryProvider) - custom RecordFormatter can be wrapped in
FixedRecordFormatterFactoryWrapper(or keepConfluentAvroToJsonFormatterFactory) - provide timestampAssigner that is able to extract time from
ConsumerRecord[K, V](see example above)
- That source now has key and value type parameters. That parameters are relevant for sources handling
-
#1741 Minor changes in
KafkaUtils,NonTransientExceptionusesInstantinstead ofLocalDateTime -
#1806 Remove old, deprecated API:
EvictableState,RichEvictableState- useEvictableStateFunctioncheckpointInterval- usecheckpointConfig.checkpointInterval- old versions of
sampleTransformers- use newer ones MiniClusterExecutionEnvironment.runningJobs()- useflinkMiniClusterHolder.runningJobs()
-
#1807 Removed
jdbcServer, please use Postgres for production-ready setups -
- RecordFormatterFactory instead of one, uses two type parameters: K, V
- ConfluentAvroToJsonFormatter is produced by ConfluentAvroToJsonFormatterFactory
- ConfluentAvroToJsonFormatter produces test data in valid JSON format, does not use Separator
- ConfluentAvroMessageFormatter has asJson method instead of writeTo
- ConfluentAvroMessageReader has readJson method instead of readMessage Example test data object:
{"keySchemaId":null,"valueSchemaId":1,"consumerRecord":{"key":null,"value":{"first":"Jan","last":"Kowalski"},"topic":"testAvroRecordTopic1","partition":0,"offset":0,"timestamp":1624279687756,"timestampType":"CreateTime","headers":{},"leaderEpoch":0}} -
#1663 Default
FlinkExceptionHandlerimplementations are deprecated, useConfigurableExceptionHandlerinstead. -
#1731 RockDB config's flag
incrementalCheckpointsis turned on by default. -
#1825 Default dashboard renamed from
flink-esptonussknacker-scenario -
#1836 Change default
kafka.consumerGroupNamingStrategytoprocessId-nodeId. -
#1357 Run mode added to nodes.
ServiceInvokerinterface was extended with new, implicitrunModeparameter. -
#1836 Change default
kafka.consumerGroupNamingStrategytoprocessId-nodeId. -
#1886 aggregate-sliding with emitWhenEventLeft = true, aggregate-tumbling and aggregate-session components now doesn't emit full context of variables that were before node (because of performance reasons and because that wasn't obvious which one context is emitted). If you want to emit some information other than aggregated value and key (availabled via new
#keyvariable), you should use#AGG.mapexpression inaggregateBy. -
#1910
processTypesrenamed toscenarioTypes. You can still use oldprocessTypesconfiguration. Old configuration will be removed in version0.5.0. -
Various naming changes:
In version 0.3.0
-
#1313 Kafka Avro API passes
KafkaConfigduringTypeInformationdetermining -
#1305 Kafka Avro API passes
RuntimeSchemaDatainstead ofSchemain various places -
#1304
SerializerWithSpecifiedClasswas moved toflink-apimodule. -
#1044 Upgrade to Flink 1.11. Current watermark/timestamp mechanisms are deprectated in Flink 1.11, new API
TimestampWatermarkHandleris introduced, withLegacyTimestampWatermarkHandleras wrapper for previous mechanisms. -
#1244
Parameterhas new parameter 'variablesToHide' withSetof variable names that will be hidden before parameter's evaluation -
#1159 #1170 Changes in
GenericNodeTransformationAPI:- Now
implementationtakes additional parameter with final state value determined duringcontextTransformation DefinedLazyParameterandDefinedEagerParameterholdsexpression: TypedExpressioninstead ofreturnType: TypingResultDefinedLazyBranchParameterandDefinedEagerBranchParameterholdsexpressionByBranchId: Map[String, TypedExpression]instead ofreturnTypeByBranchId: Map[String, TypingResult]
- Now
-
- Now
SimpleSlidingAggregateTransformerV2andSlidingAggregateTransformeris deprecated in favour ofSlidingAggregateTransformerV2 - Now
SimpleTumblingAggregateTransformeris deprecated in favour ofTumblingAggregateTransformer - Now
SumAggregator,MaxAggregatorandMinAggregatordoesn't change type of aggregated value (previously was changed to Double) - Now
SumAggregator,MaxAggregatorandMinAggregatorreturn null instead of0D/Double.MaxValue/Double.MinValuefor case when there was no element added beforegetResult
- Now
-
#1149 FlinkProcessRegistrar refactor (can affect test code)
-
#1166
model.confshould be renamed todefaultModelConfig.conf -
#1218 FlinkProcessManager is no longer bundled in ui uber-jar. In docker/tgz distribution
-
#1255 Moved displaying
Metrics tabtocustomTabs -
#1257 Improvements: Flink test util package
- Added methods:
cancelJob,submitJob,listJobs,runningJobstoFlinkMiniClusterHolder - Deprecated:
runningJobs, fromMiniClusterExecutionEnvironment - Removed:
getClusterClientfromFlinkMiniClusterHolderinterface, because of flink compatibility at Flink 1.9 - Renamed:
FlinkStreamingProcessRegistrartoFlinkProcessManager
- Added methods:
-
#1303 TypedObjectTypingResult has a new field: additionalInfo
In version 0.2.0
-
#1104 Creation of
FlinkMiniClusteris now extracted fromStoppableExecutionEnvironment. You should create it using e.g.:val flinkMiniClusterHolder = FlinkMiniClusterHolder(FlinkTestConfiguration.configuration(parallelism))
flinkMiniClusterHolder.start()and then create environment using:
flinkMiniClusterHolder.createExecutionEnvironment(). At the end you should cleanup
flinkMiniClusterHolderby:flinkMiniClusterHolder.stop().
FlinkMiniClusterHoldershould be created once for test class - it is thread safe and resource expensive.MiniClusterExecutionEnvironmentin the other hand should be created for each process. It is not thread safe because underlyingStreamExecutionEnvironmentis not. You can useFlinkSpecto achieve that. -
pl.touk.nussknacker.engine.queryablestate.QueryableClientwas moved fromqueryableStatemodule topl.touk.nussknacker.engine.api.queryablestatepackage inapimodulepl.touk.nussknacker.engine.queryablestate.QueryableStatewas moved topl.touk.nussknacker.engine.api.queryablestate- CustomTransformers from
pl.touk.nussknacker.engine.flink.util.transformerinflinkUtilmodule were moved to newflinkModelUtilmodule. pl.touk.nussknacker.engine.testing.EmptyProcessConfigCreatorwas moved frominterpretermodule topl.touk.nussknacker.engine.util.processpackage inutilmodule
-
#1039 Generic parameter of
LazyParameter[T]has upper bound AnyRef now to avoid problems with bad type extraction. It caused changesAnytoAnyRefin a few places - mainlyFlinkLazyParameterFunctionHelperandFlinkCustomStreamTransformation -
#1039
FlinkStreamingProcessRegistrar.applyhas a new parameter of typeExecutionConfigPreparer. In production code you should passExecutionConfigPreparer.defaultChain()there and in test code you should passExecutionConfigPreparer.unOptimizedChain(). See scaladocs for more info. If you already have done some Flink'sExecutionConfigset up before you've registered process, you should consider create your own chain usingExecutionConfigPreparer.chain(). -
#1039
FlinkSourceFactorydoesn't takeTypeInformationtype class as a generic parameter now. Instead of this, it takesClassTag.TypeInformationis determined during source creation.typeInformation[T]method was moved fromBasicFlinkSourcetoFlinkSourcebecause still must be some place to determine it for tests purpose. -
#965 'aggregate' node in generic model was renamed to 'aggregate-sliding'
-
#922 HealthCheck API has new structure, naming and JSON responses:
- old
/healthCheckis moved to/healthCheck/process/deployment - old
/sanityCheckis moved to/healthCheck/process/validation - top level
/healthCheckindicates general "app-is-running" state
- old
-
#879 Metrics use variables by default, see docs to enable old mode, suitable for graphite protocol. To use old way of sending:
- put
globalParameters.useLegacyMetrics = truein each model configuration (to configure metrics sending in Flink) - put:
countsSettings {
user: ...
password: ...
influxUrl: ...
metricsConfig {
nodeCountMetric: "nodeCount.count"
sourceCountMetric: "source.count"
nodeIdTag: "action"
countField: "value"
}
} - put
-
Introduction to KafkaAvro API: #871, #881, #903, #981, #989, #998, #1007, #1014, #1034, #1041
API for KafkaAvroSourceFactory was changed:
KafkaAvroSourceFactory old way:
val clientFactory = new SchemaRegistryClientFactory
val source = new KafkaAvroSourceFactory(
new AvroDeserializationSchemaFactory[GenericData.Record](clientFactory, useSpecificAvroReader = false),
clientFactory,
None,
processObjectDependencies = processObjectDependencies
)
KafkaAvroSourceFactory new way :
val schemaRegistryProvider = ConfluentSchemaRegistryProvider(processObjectDependencies)
val source = new KafkaAvroSourceFactory(schemaRegistryProvider, processObjectDependencies, None)
Provided new API for Kafka Avro Sink:
val kafkaAvroSinkFactory = new KafkaAvroSinkFactory(schemaRegistryProvider, processObjectDependencies)
Additional changes:
- Bump up confluent package to 5.5.0
- (Refactor Kafka API) Moved
KafkaSourceFactorytopl.touk.nussknacker.engine.kafka.sinkpackage - (Refactor Kafka API) Changed
BaseKafkaSourceFactory, now it requiresdeserializationSchemaFactory: KafkaDeserializationSchemaFactory[T] - (Refactor Kafka API) Moved
KafkaSinkFactorytopl.touk.nussknacker.engine.kafka.sourcepackage - (Refactor Kafka API) Renamed
SerializationSchemaFactorytoKafkaSerializationSchemaFactory - (Refactor Kafka API) Renamed
DeserializationSchemaFactorytoKafkaDeserializationSchemaFactory - (Refactor Kafka API) Renamed
FixedDeserializationSchemaFactorytoFixedKafkaDeserializationSchemaFactory - (Refactor Kafka API) Renamed
FixedSerializationSchemaFactorytoFixedKafkaSerializationSchemaFactory - (Refactor Kafka API) Removed
KafkaSerializationSchemaFactoryBase - (Refactor Kafka API) Replaced
KafkaKeyValueSerializationSchemaFactoryBasebyKafkaAvroKeyValueSerializationSchemaFactory(it handles only avro case now) - (Refactor Kafka API) Removed
KafkaDeserializationSchemaFactoryBase - (Refactor Kafka API) Replaced
KafkaKeyValueDeserializationSchemaFactoryBasebyKafkaAvroKeyValueDeserializationSchemaFactory(it handles only avro case now) - (Refactor KafkaAvro API) Renamed
AvroDeserializationSchemaFactorytoConfluentKafkaAvroDeserializationSchemaFactoryand moved toavro.schemaregistry.confluentpackage - (Refactor KafkaAvro API) Renamed
AvroKeyValueDeserializationSchemaFactorytoConfluentKafkaAvroDeserializationSchemaFactoryand moved toavro.schemaregistry.confluentpackage - (Refactor KafkaAvro API) Renamed
AvroSerializationSchemaFactorytoConfluentAvroSerializationSchemaFactoryand moved toavro.schemaregistry.confluentpackage - (Refactor KafkaAvro API) Renamed
AvroKeyValueSerializationSchemaFactorytoConfluentAvroKeyValueSerializationSchemaFactoryand moved toavro.schemaregistry.confluentpackage - (Refactor KafkaAvro API) Removed
FixedKafkaAvroSourceFactoryandFixedKafkaAvroSinkFactory(now we don't support fixed schema) - (Refactor Kafka API) Replaced
topics: List[String]byList[PreparedKafkaTopic]and removedprocessObjectDependenciesinKafkaSource
Be aware that we are using Avro 1.9.2 instead of default Flink's 1.8.2 (for Java time logical types conversions purpose).
- #1013 Expression evaluation is synchronous now. It shouldn't cause any problems (all languages were synchronous anyway), but some internal code may have to change.
In version 0.1.2
- #957 Custom node
aggregatefromgenericmodel has changed parameter fromwindowLengthInSecondstowindowLengthwith human friendly duration input. If you have used it in process, you need to insert correct value again. - #954
TypedMapis not a case class wrapping scala Map anymore. If you have done some pattern matching on it, you should usecase typedMap: TypedMap => typedMap.asScalainstead.
In version 0.1.1
- #930
DeeplyCheckingExceptionExtractorwas moved fromnussknacker-flink-utilmodule tonussknacker-utilmodule. - #919
KafkaSourceconstructor now doesn't takeconsumerGroup. Instead of this it computesconsumerGroupon their own based onkafka.consumerGroupNamingStrategyinmodelConfig(default set toprocessId). You can also override it byoverriddenConsumerGroupoptional parameter. Regards to this changes,KafkaConfighas new, optional parameterconsumerGroupNamingStrategy. - #920
KafkaSourceconstructor now takesKafkaConfiginstead of using one that was parsed byBaseKafkaSourceFactory.kafkaConfig. Also if you parse Typesafe Config toKafkaSourceon your own, now you should use dedicated methodKafkaConfig.parseConfigto avoid further problems when parsing strategy will be changed. - #914
pl.touk.nussknacker.engine.api.definition.Parameterhas deprecated main factory method withruntimeClassparameter. Now should be passedisLazyParameterinstead. Also were removedruntimeClassfrom variances of factory methods prepared for easy testing (optionalmethod and so on).
In version 0.1.0
- #755 Default async execution context does not depend on parallelism.
asyncExecutionConfig.parallelismMultiplierhas been deprecated and should be replaced withasyncExecutionConfig.workers. 8 should be sane default value. - #722 Old way of configuring Flink and model (via
flinkConfigandprocessConfig) is removed.processTypesconfiguration should be used from now on. Example:becomes:flinkConfig {...}
processConfig {...}processTypes {
"type e.g. streaming" {
deploymentConfig {
type: "flinkStreaming"
PUT HERE PROPERTIES OF flinkConfig FROM OLD CONFIG
}
modelConfig {
classPath: PUT HERE VALUE OF flinkConfig.classPath FROM OLD CONFIG
PUT HERE PROPERTIES OF processConfig FROM OLD CONFIG
}
}
} - #763 Some API traits (ProcessManager, DictRegistry DictQueryService, CountsReporter) now extend
java.lang.AutoCloseable. - Old way of additional properties configuration should be replaced by the new one, which is now mapped to
Map[String, AdditionalPropertyConfig]. Example in your config:becomes:additionalFieldsConfig: {
mySelectProperty {
label: "Description"
type: "select"
isRequired: false
values: ["true", "false"]
}
}additionalPropertiesConfig {
mySelectProperty {
label: "Description"
defaultValue: "false"
editor: {
type: "FixedValuesParameterEditor",
possibleValues: [
{"label": "Yes", "expression": "true"},
{"label": "No", "expression": "false"}
]
}
}
} - #588 #882
FlinkSourceAPI changed, current implementation is nowBasicFlinkSource - #839 #882
FlinkSinkAPI changed, current implementation is nowBasicFlinkSink - #841
ProcessConfigCreatorAPI changed; note that currently all process objects are invoked withProcessObjectDependenciesas a parameter. The APIs ofKafkaSinkFactory,KafkaSourceFactory, and all their implementations were changed.Configis available as property ofProcessObjectDependenciesinstance. - #863
restUrlindeploymentConfigneed to be preceded with protocol. Host with port only is not allowed anymore. - Rename
grafanaSettingstometricsSettingsin configuration.
In version 0.0.12
- Upgrade to Flink 1.7
- Refactor of custom transformations, dictionaries, unions, please look at samples in example or generic to see API changes
- Considerable changes to authorization configuration, please look at sample config to see changes
- Circe is now used by default instead of Argonaut, but still can use Argonaut in Displayable
In version 0.0.11
- Changes in CustomStreamTransformer implementation, LazyInterpreter became LazyParameter, please look at samples to see changes in API
In version 0.0.8
- Upgrade to Flink 1.4
- Change of format of Flink cluster configuration
- Parameters of sources and sinks are expressions now - automatic update of DB is available
- Change of configuration of Grafana dashboards
- Custom processes are defined in main configuration file now