{"id":19176889,"url":"https://github.com/oasisdigital/nges","last_synced_at":"2025-05-07T19:42:23.564Z","repository":{"id":90493019,"uuid":"80235664","full_name":"OasisDigital/nges","owner":"OasisDigital","description":"Next Generation Event Store - An event store implemented as an embeddable Java library. Event persistence in PostgreSQL, JGroups multicast hinting for immediate (and still strictly ordered) event delivery. An audacious name for a modest library.","archived":false,"fork":false,"pushed_at":"2017-02-12T16:36:36.000Z","size":98,"stargazers_count":15,"open_issues_count":1,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-27T10:06:00.766Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OasisDigital.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-27T18:47:21.000Z","updated_at":"2024-05-11T12:36:12.000Z","dependencies_parsed_at":null,"dependency_job_id":"f31b8ed4-b1cd-40d2-b2e7-222aa2e00e11","html_url":"https://github.com/OasisDigital/nges","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OasisDigital%2Fnges","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OasisDigital%2Fnges/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OasisDigital%2Fnges/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OasisDigital%2Fnges/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OasisDigital","download_url":"https://codeload.github.com/OasisDigital/nges/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252945803,"owners_count":21829661,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T10:30:59.448Z","updated_at":"2025-05-07T19:42:23.557Z","avatar_url":"https://github.com/OasisDigital.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NGES - \"Next Generation Event Store\"\n\n[![Build Status](https://travis-ci.org/OasisDigital/nges.svg?branch=master)](https://travis-ci.org/OasisDigital/nges)\n\nCopyright 2015-2016 Oasis Digital Solutions Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this project except in compliance with the License.\n\n## Introduction\n\nNGES is a minimalist event store, in the form of an embeddable Java library\nconnecting to PostgreSQL database. Features include:\n\n* Saving events grouped into streams. Every event is given a global sequential ID as\n  well as sequence-local sequence number.\n* Querying - events for all streams or one particular stream in sequence.\n* Notifications - plug in to JGroups cluster to get notifications every time an event\n  is saved. The cluster can also be used for any application-specific messages.\n* Concurrency control:\n  * Optimistic: version-based, preventing concurrent updates on the same stream\n  * Pessimistic: lease-based locking, for arbitrary scopes\n\n## Motivation\n\nThis design, as a library rather than as a (currently more trendy) standalone (micro)\nservice, is motivated by deployment ease. A system of built around an event store is\ncritically dependent on the uptime of that event store; by depending only on PostgreSQL\nas a central data store, existing system administration expertise can be used. But the\ndatabase alone does not readily accommodate efficient immediate propagation of events,\nso we supplement it with JGroups as a clusterable (again, using off-the-shelf system\nadministration skills) mechanism to propagate changes immediately.\n\n## Higher Level Tools\n\nNGES can serve as an effective low-level event store for an event source (\"CQRS\") system;\nsuch a system would also benefit from another layer of tools, abstracting out the numerous\ncommon concerns in implementing projections and other major application components.\nCurrently such layers are not yet included in NGES, could be in the future.\n\n## Dependencies\n\nThis project aims to have as few external dependencies as reasonably possible. It depends on:\n\n* PostgreSQL (runtime)\n* PostgreSQL JDBC driver\n* JGroups\n* Guava\n\n## Usage\n\nIt's recommended to create an `EventStoreContext` to wire all the pieces together.\nIt comes with reasonable defaults and only needs a `DataSource`.\n\n### Append and Query\n\n    // Initialize context\n    EventStoreContext ctx = new EventStoreContext(dataSource);\n    ctx.initialize();\n    EventStore eventStore = ctx.getEventStore();\n\n    // Save an event\n    UUID streamId = UUID.randomUUID();\n    UUID correlationId = UUID.randomUUID();\n    Event event = new Event(streamId,\n                            \"EventStoreDemonstrated\",\n                            correlationId,\n                            \"{\\\"test\\\": \\\"Any JSON payload\\\"}\");\n    eventStore.save(Arrays.asList(event), \"MyStream\", EventStore.NEW_STREAM);\n\n    // Get up to 100 events after event ID 0\n    eventStore.getEventsForAllStreams(0, 100);\n\n    // Get up to 100 events for given stream ID, after sequence 0 within that stream\n    eventStore.getEventsForStream(streamId, 0, 100);\n\n    // Clean up - shut down JGroups cluster and JMX monitoring\n    ctx.destroy();\n\n### JGroups Notifications\n\nIn order to be notified about new notifications, register a handler on the `MessageGroup`.\nIt uses Guava (local) event bus under the hood, so the handler should have Guava's `@Subscribe` method.\n\n    class Subscriber {\n        @Subscribe\n        public void on(EventUpdate eventUpdate) {\n            System.out.println(\"Last event ID is: \" + eventUpdate.getEventId());\n        }\n    }\n\n    MessageGroup messageGroup = ctx.getMessageGroup();\n    messageGroup.registerSubscriber(new Subscriber());\n\nNGES publishes messages of type `EventUpdate` every few seconds, or as soon as new events are saved in the\nstore. However, this cluster can also be used for custom application-level messages.\n\n    class MyApplicationSubscriber {\n        @Subscribe\n        public void on(NewUserRegistered event) {\n            // ...\n        }\n    }\n\n    messageGroup.registerSubscriber(new MyApplicationSubscriber());\n\n    messageGroup.publish(new NewUserRegistered(userId, login));\n\nThis is a lightweight messaging solution. It doesn't offer many of the features of persistent message\nqueues, but it's very easy to set up, has minimal footprint and may come in handy. It is intended not\nas a domain level message queue, but rather as a way to propagate information around all application\nservers in the cluster.\n\n## Database Schema\n\nNGES uses the following database schema:\n\n    create table event_log (\n      event_id bigserial primary key,\n      transaction_time timestamptz default current_timestamp,\n      type varchar,\n      stream_id uuid not null,\n      correlation_id uuid not null,\n      seq_no bigint not null,\n      payload json\n    );\n\n    create index event_log_by_stream_seq on event_log(stream_id, seq_no);\n    create index event_log_by_transaction_time on event_log(transaction_time);\n\n    create table event_stream_list (\n      stream_id uuid not null primary key,\n      stream_type varchar not null,\n      last_event_id bigint,\n      last_transaction_time timestamptz,\n      last_seq_no bigint\n    );\n\n    create table lease (\n      lease_key varchar not null primary key,\n      owner_key varchar not null,\n      expiration_date timestamptz\n    );\n\n## Additional Resources\n\n* [Linear Event Store](http://blog.oasisdigital.com/2015/cqrs-linear-event-store/),\n   a post on the Oasis Digital blog describing benefits of using a\n   linear event store like this one.\n\n## Demo\n\nSee nges-sample-tic-tac-toe for a complete web application based on the NGES.\n\n## Building\n\nIn order to build the project:\n\n1. Install PostgreSQL and create a new database (for integration tests).\n2. Copy config/SAMPLE.application.properties to config/application.properties\n   and adjust it to match your setup.\n3. Run Gradle build task.\n\nThe schema can be found in db_schema directory. The build process applies it with Flyway using the\nflywayMigrate task.\n\nOnce the configuration is in place and database has the schema installed, the tests can be ran from IDE or\nwith Gradle.\n\nIn order to install the project to your local Maven repository for use with other projects, run the Gradle\ninstall task.\n\n## Should I use this?\n\nWe built the library to support a very complex project; it has its own\nsuite of tests, and is also been validated thoroughly by that\napplications tests. It suits our needs there, operating as a library\nrather than as another service to be managed. We believe it is of\ngood quality, and has some very worthwhile technical merits.\n\nWith that in mind, if you are looking for a production proven event\nstore with more features, support services available, etc., then we\nrecommend the popular \"Event Store\", also sometimes called \"Greg's Event\nStore\", named after Greg Young who is done so much to popularize the\nmerit of event sourcing:\n\nhttps://geteventstore.com/\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foasisdigital%2Fnges","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foasisdigital%2Fnges","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foasisdigital%2Fnges/lists"}