
Announcing Horizon 2: query aggregation, Auth0 integration, WebSockets
Today we’re pleased to announce the official release of Horizon 2.0, codenamed Mt. Whitney. You can install it today from npm.
Horizon 2.0 introduces a powerful new query aggregation feature, support for the Auth0 cloud service, several noteworthy architectural changes, and many bug fixes. The release represents the first round of improvements that we’ve implemented in collaboration with our user community since Horizon’s launch in May.
Aggregation queries
Query aggregation is the most significant new feature in version 2.0. The new
aggregate
and model
functions provide a way to combine multiple Horizon
queries, making it easy to track their collective output:
let hz = Horizon()
let aggregated = hz.aggregate({
owner: hz("people").find("bob"),
pet: hz("animals").find("spot"),
related: {
friends: hz("people").findAll({friendOf: "bob"}).limit(10),
petFriends: hz("animals").findAll({friendOf: "spot"}).limit(10)
},
someConstant: "Always have this here",
})
You can invoke the aggregate
function on a Horizon
instance. Its parameter
is an object that associates named properties with Horizon queries or other
compatible values. You can chain a fetch
or watch
operation to the end of an
aggregation, allowing you to either retrieve the values once or track the
changes on an ongoing basis. When you watch
an aggregation, it will emit
updates any time one of the aggregated sub-queries has new results.
In addition to Horizon queries, aggregations can also include literal values, Observables, Promises, and arrays or objects that contain any of those supported values. Aggregations are powerful tools for composing multi-faceted queries.
You can also take advantage of various RxJS features to use Horizon aggregations for query orchestration and flow control. For example, the following code demonstrates how to use an Observable timer alongside a query in an aggregation to force the output to emit on the timed interval in addition to when the query receives an update:
hz.aggregate({
counter: Observable.timer(0, 1000),
someQuery: hz("foo").find("bar"),
}).watch().subscribe({ next(x){ console.log(x) }})
The model
function is a convenience method that provides a shorthand for
parameterizing aggregates, wrapping them in a callable function that lets you
pass in arguments:
let myModel = hz.model((a, b, c) => ({
foo: hz("foo").find(a),
bar: hz("bar").find(b),
baz: hz("baz").find(c)
});
var modelA = myModel(1, 2, 3);
var modelB = myModel(2, 3, 4);
You can optionally nest your models, which is often useful when you want to compose complex operations from smaller, reusable parts. For more details and more comprehensive examples, refer to the official documentation.
Auth0 integration
Auth0 is a popular identity management and single sign-on service. It’s available as an on-premise or hosted cloud platform that can handle authentication and user management for applications, with optional support for a selection of third-party OAuth providers.
You can use Auth0 with Horizon to enable conventional username/password authentication or to take advantage of their broader range of OAuth provider integrations. Horizon’s Auth0 support was contributed by community member Anton Poznyakovskiy.
Native WebSockets
We made some important changes to Horizon’s underlying network plumbing in version 2.0. The new version uses plain WebSockets for realtime messaging instead of engine.io. Given the ubiquity of native WebSocket support in browsers and other environments, many of you have indicated that you prefer the simplicity of a straightforward WebSocket-based protocol over the flexibility of engine.io’s transport-neutral abstraction layer.
Using vanilla WebSockets instead of engine.io simplifies some high-scalability deployment scenarios, particularly in cases where reverse proxies are involved. With the transition away from engine.io, Horizon no longer provides a built-in long-polling fallback. We are still evaluating possible avenues for making Horizon’s network transport layer extensible in the future.
Simplifying interoperability with RethinkDB
Horizon 2.0 includes a number of improvements that reduce friction for developers who want to build Horizon applications that interoperate with other RethinkDB applications or microservices.
When the Horizon backend creates the underlying RethinkDB table for a collection, the table and collection name are now consistent- -there’s no longer a random hash at the end of the table name. You can also insert data into the Horizon tables without manually adding a version field.
Horizon Roadmap
Horizon is still under heavy active development. In response to user feedback and lessons we learned from building our own applications with Horizon, we’re revisiting many of our early architectural decisions. You can expect to see a fair amount of churn in the coming months as we continue to overhaul key parts of the Horizon stack. Some of the coming changes may be disruptive, but they will result in a better developer experience as Horizon matures and becomes more suitable for adoption in production environments.
The 2.0 release addresses many of the most pressing concerns raised by Horizon early adopters. Our next big project is the design and implementation of a plugin system. Plugins will give users the ability to extend Horizon with additional features and capabilities. Additionally, the plugin system will make it easier for us to incorporate large features–like support for REST endpoints and adding custom Horizon commands–with less disruption to Horizon’s core.
We’re also exploring ways to make Horizon integrate more seamlessly with the rest of the Node.js ecosystem. In the long term, we aim to make Horizon more modular and easier to embed, while simultaneously taking better advantage of existing Node.js server and middleware frameworks. Those changes will have significant implications for how Horizon and applications that embed Horizon will handle authentication and other major parts of the developer experience.
We conduct all ongoing Horizon development in the open, with the direct involvement of our community. You can participate in the process and help shape the future of the Horizon stack. To learn more about our nascent plans for Horizon’s plugin system, you can follow the discussion on GitHub.
Conclusion
To see all of the features and improvements that we incorporated into the
Horizon 2.0 release, check out the release milestone in our issue
tracker on GitHub. For details about migrating your Horizon project from 1.x to
2.x, please refer to the compatibility notes in the
Horizon 2.0 discussion thread. The Horizon command line tool includes
a new hz migrate
command to help you seamlessly transition your project to new
versions of Horizon.
We’re especially grateful to the users who contributed to this release by providing feedback, feature recommendations, bug reports, and pull requests. Thank you for your support!