With 4.11 we are excited to introduce legacy compatibility for DQL, which allows developers to use the new DQL APIs while maintaining compatibility with existing code and data. This capability, called STRICT MODE, is designed to ease the transition to the new APIs and ensure that existing applications continue to function as expected.
DQL Strict Mode provides control over how DQL statements are evaluated and how data types are inferred. When disabled, it offers more flexibility in working with documents without requiring explicit collection definitions.
DQL Strict Mode
With strict mode disabled (DQL_STRICT_MODE=false
), Ditto is more flexible and will infer the CRDT type based on the document’s shape:
Setting DQL Strict Mode
DQL 4.11 introduces a new Differ
API for calculating diffs between query results.
This API can be used with a store observer to understand how its results change
over successive callbacks. The Differ
API provides a way to track changes in
the data and can be used to optimize data synchronization and conflict resolution.
DQL 4.11 introduces support for transactions. Transactions can be used to group multiple DQL statements together, ensuring that either all of the statements are executed successfully or none of them are. This is particularly useful in scenarios where multiple updates or inserts need to be made to the database, and you want to ensure that either all of them are applied or none of them are.
Transactions API documentation.
DQL 4.11 introduces numerous advanced querying and manipulation features:
Feature | Description | Example |
---|---|---|
UNSET clause | Remove fields from documents | UPDATE orders UNSET items.abc WHERE _id = 'my-id' |
CAST function | Explicitly convert between data types | SELECT * FROM products WHERE CAST(price AS INT) > 10 |
USE IDS clause | Direct document retrieval by ID | SELECT * FROM products USE IDS '123', '456' |
SIMILAR TO | Pattern matching expressions | SELECT * FROM products WHERE name SIMILAR TO '%phone%' |
Runtime expressions | Use expressions in object/array construction | UPDATE products SET metadata = { 'updated_at': current_timestamp() } |
Counters | Support for legacy compatible counter type | UPDATE products APPLY in_stock PN_INCREMENT BY 1.0 |
In 4.11, functional operations are denoted with an arrow (->
) are deprecated. Read more.
The tombstone reaper is now enabled by default for all SDKs. This feature helps clean up deleted document markers (tombstones) to improve database performance and reduce storage requirements.
The reaper:
This improves overall system performance by reducing the long-term accumulation of
tombstones when calling DELETE
to remove documents.
DQL_STRICT_MODE
as a system parameter to opt-out of requiring collection definitions (#16573)network_use_nextgen_multihop_stack
(#16370)DittoDiff
class to represent diffs produced by the DittoDiffer
DittoDiffer
class for calculating diffs between query resultstransaction()
method on DittoStore
for performing DQL transactionsDittoTransaction
class to represent an active DQL transactionDittoTransactionInfo
class for transaction informationDittoTransactionCompletionAction
for commit/rollback actionsWe’ve enhanced our TLS certificate handling to provide more robust and reliable secure connections while maintaining our high security standards.
We’ve enhanced our query capabilities with improved sorting and filtering for UPDATE operations, while also focusing on overall reliability improvements.
isStopped
property of AttachmentFetcher
instances now becomes true
after completing an attachment fetchQueryResult
and QueryResultItem
ditto.store.newAttachment
now returns a Future<Attachment>
rather than an Attachmentditto.close()
now returns a Future<void>
rather than void
Ditto’s Flutter SDK now supports Flutter 3.19 and later, broadening compatibility and making it easier for more developers to integrate Ditto into their apps. This update ensures greater flexibility, allowing teams to adopt Ditto without needing to upgrade immediately to the latest Flutter version.
The Ditto team is excited to preview support for Hot Restarts in Flutter.
To allow users experiment and provide feedback on hot restarts we’ve shipped a specific SDK version with hot restarts enabled by default.
To use hot restarts update your version to 4.10.0-experimental-hot-restart.0
. This version is identical to 4.10.0
but
has Hot Restart enabled by default. In a upcoming release this capability will be integrated into Ditto’s standard package
as a developer mode config that can be set by the user on Ditto class initialization.
Flutter Dart has limited support for Hot Restarts with native binaries, such as Ditto. The Ditto team is working to mitigate these issues. If you run into any issues while experimenting with Flutter Hot Restarts reach out to Ditto Customer Support.
Known issues include:
DittoLogger.isEnabled = false
immediately after calling await Ditto.init()
.4.10.0-experimental-hot-restart.0
.Ditto.init()
(#15880)stopSync()
is called (#SDKS-707) Fixed: Fixed a bug that caused
observer events to not be triggered in profile and release mode (either via the onChange
parameter
or the StoreObserver.changes
stream)
Added: Support for Flutter 3.19 for iOS and Android
Changed: Failing to call
await Ditto.init()
will now throw. This is to prevent improper initialization.
Changed: ditto.transportsConfig = config;
will now throw if config
enables
transports which don’t exist on the current platform (e.g. AWDL on Android or P2P Wifi on iOS).
TransportConfig.setAllPeerToPeerEnabled()
will now take the current platform
into account, and will only modify transports which are available. A newly
created Ditto
instance will not have transports enabled that are not
available on the current platform
Fixed: Resolve an uncaught exception
that could happen in ditto.presence.graph
when there were P2PWifi connections.
Fixed: The persistence directory behaves differently if a relative path is provided.
If a relative path is provided, it will be treated as a subdirectory of
getApplicationDocumentsDirectory()
. If an absolute path is given, its value
is not modified. The persistenceDirectory
parameter in Ditto.open
is now
optional, and defaults to "ditto"
. If the directory does not exist, it will be created.
We’re excited to announce the General Availability of the Ditto Flutter SDK! Designed to empower developers building cross-platform apps, the Flutter SDK delivers reliable real-time data synchronization and offline-first capabilities, now production-ready!
General Availability (GA) means API stability! Starting with 4.9.0
Ditto will guarantee semver
support of all APIs following industry standards. For more on semver see
semver.org.
To provide the best product with our GA release we’ve made some final modifications to the underlying architecture that bridges Dart and the Ditto Core for Android. The goal with this change is to provide a higher quality product with improved performance, reliability, and developer experience.
These changes provide the following benefits:
This release contains a handful of minor syntax changes to provide an improved developer experience and better support the underlying framework. These syntax changes all stem from the ability to support non-async calls across the Dart-Ditto Core FFI.
In the initial Dart-Ditto implementation all Dart internal calls were required to make async calls
into Ditto. This required us to make all Ditto API methods async
. Due to the improvements
with our recent changes we are now able to provide synchronous methods. This change will bring a more
natural developer experience.
await Ditto.init()
From 4.9.0
and later it’s required to call await Ditto.init()
before using any Ditto
functionality. Failing to do so can result in incorrect initialization of Ditto and unexpected
failures.
Notably, this must happen after WidgetsFlutterBinding.ensureInitialized()
has
been called.
Flutter’s runApp
already calls
WidgetsFlutterBinding.ensureInitialized()
, so if calling Ditto.init()
inside
the initState
of a StatefulWidget
, it will just work.
To initialize Ditto
in main
, use the following syntax:
asnyc
functions have become syncSelect functions that don’t require asynchronous execution have been converted from async
to standard sync operations.
Changed Methods Include:
ditto.startSync();
ditto.store.registerObserver(...);
ditto.sync.registerSubscription(...);
Example with basic replacement:
Example chaining Future’s with .then()
(often seen in initState()
):
Async getter/setter method pairs have been converted to properties using Dart’s getter/setter syntax, for a more natural developer experience.
Changed Methods Include:
Previous | New |
---|---|
DittoLogger.setMinimumLogLevel(...) DittoLogger.getMinimumLogLevel(...) | DittoLogger.minimumLogLevel |
DittoLogger.setCustomLogCallback(...) DittoLogger.getCustomLogCallback(...) | DittoLogger.customLogCallback |
Examples
getFoo
/setFoo
to isFoo
For property types where the value type is bool
, the functions will have been renamed
from getFoo
and setFoo
to isFoo
.
Changed Methods Include:
Previous | New |
---|---|
DittoLogger.setEnabled() DittoLogger.getEnabled() | DittoLogger.isEnabled |
ditto.setTransportConfig() ditto.getTransportConfig() | ditto.transportConfig |
Examples
Objects with async
constructors that didn’t require asynchronous initialization have
been changed for a more natural developer experience.
Changed Methods Include:
Identity
subclass (E.g. OnlinePlaygroundIdentity
)Example:
Many of our types are now either final
classes (which prevent all
subtyping), or interface
classes (which allow implements
but disallow
other forms of subtyping).
If you were previously extending or implementing a type and this is now disallowed, you can create a wrapper type:
Example:
Some types may explicitly allow subtyping. Follow the API docs to understand when subtyping is best used.
dart:io
types in public APIDirectory
and File
are no longer found in our public API.
For example Ditto.open()
previously took a Directory persistenceDirectory
,
but this has been changed to String
.
This can be resolved by calling .path
:
Supporting new Android capabilities requires using Kotlin Gradle Plugin version 1.8.0
or later.
To upgrade:
./android/settings.gradle
org.jetbrains.kotlin.android
plugin to 1.8.0
Final Preview Release
Contains: Reliability and stability improvements.
We’re excited to announce the public preview of the Ditto Flutter SDK!
While you can expect major feature compatibility with our production SDKs, we’re continuously refining the experience and closing any minor gaps. Join us on this journey, and share your feedback to help shape the future of Ditto for Flutter!
This change has a large number of new capabilities as well as some minor namings API Breaking Changes.
Added: Presence API - Allows receiving syncing information about other peers. See Using Mesh Presence
Added: WifiAware as a Transports protocol.
Added: Retrieving active subscriptions. Syncing Data > Retrieving Subscriptions
Added: Canceling subscriptions. Syncing Data > Canceling Subscriptions
Added: Support for sync groups. Creating Sync Groups
Added: Support to intercept and reject new connections. Handling Connection Requests
Breaking change: AuthenticationStatus.authenticated renamed to isAuthenticated
Breaking change: Various TransportConfig-related types have enabled properties renamed to isEnabled
Breaking change: HttpListenConfig.interfaceIp renamed to interfaceIP
Breaking change: HttpListenConfig.websocketSync renamed to webSocketSync
Breaking change: StoreObserver.cancelled renamed to isCancelled
Added: Logger class that provides diagnostics capabilities. Added: Device Dashboard Support - customers can now see device information on the Ditto Portal. Added: Support for Attachments.
Changed: The default deviceName
will now represent the device’s model.
Added: OnlineWithAuthenticationIdentity and ditto.auth
Added: User-configurable transport config. Customizing Transports Configurations
Added: Ability to stop sync ditto.stopSync()
Fixed: Cancelling a subscription currently doesn’t trigger any action
Fixed: Observer API no longer fires every 50ms. Previously the observer API was using a polling mechanism internally which resulted in an event ever 50ms no matter if there were changes or not. This has been updated with an event listener pattern.
Changed: Performance and battery life improvements from observers not continuously firing
Version 4.8.0-beta.6 has been Retracted due to an issue found with Android observer API not firing correctly.
Please use earlier or later releases.
The initial beta release of Flutter