public void read_store_all_records() { var stream = Guid.NewGuid().ToString(); using (var store = new FileAppendOnlyStore(new DirectoryInfo(_storePath))) { store.Initialize(); var currentVersion = store.GetCurrentVersion(); for (int i = 0; i < 2; i++) { store.Append(stream, Encoding.UTF8.GetBytes("test message" + i)); } var records = store.ReadRecords(-1, Int32.MaxValue).ToArray(); Assert.AreEqual(currentVersion + 2, records.Length); for (var i = currentVersion; i < currentVersion + 2; i++) { Assert.AreEqual("test message" + (i - currentVersion), Encoding.UTF8.GetString(records[i].Data)); Assert.AreEqual(i - currentVersion + 1, records[i].StreamVersion); Assert.AreEqual(i + 1, records[i].StoreVersion); } } }
public static FileAppendOnlyStore CreateAppendOnlyStore(this FileStorageConfig cfg, string name) { var store = new FileAppendOnlyStore(new DirectoryInfo(Path.Combine(cfg.FullPath, name))); store.Initialize(); return(store); }
public void append_data() { _store.Initialize(); var currentVersion = _store.GetCurrentVersion(); const int messagesCount = 3; for (int i = 0; i < messagesCount; i++) { _store.Append("stream1", Encoding.UTF8.GetBytes("test message" + i)); } var data = _store.ReadRecords("stream1", currentVersion, Int32.MaxValue).ToArray(); for (int i = 0; i < messagesCount; i++) { Assert.AreEqual("test message" + i, Encoding.UTF8.GetString(data[i].Data)); } Assert.AreEqual(messagesCount, data.Length); }
public void get_current_version() { using (var store = new FileAppendOnlyStore(new DirectoryInfo(_storePath))) { store.Initialize(); var currentVersion = store.GetCurrentVersion(); store.Append("versiontest", Encoding.UTF8.GetBytes("test message1")); store.Append("versiontest", Encoding.UTF8.GetBytes("test message2")); store.Append("versiontest", Encoding.UTF8.GetBytes("test message3")); Assert.AreEqual(currentVersion + 3, store.GetCurrentVersion()); } }
public void append_data_when_set_version_where_does_not_correspond_real_version() { var key = Guid.NewGuid().ToString(); using (var store = new FileAppendOnlyStore(new DirectoryInfo(_storePath))) { store.Initialize(); store.Append(key, Encoding.UTF8.GetBytes("test message1"), 100); var data = store.ReadRecords(key, -1, 2).ToArray(); CollectionAssert.IsEmpty(data); } }
public void SetUp() { _serializer = new TestMessageSerializer(new[] { typeof(TestEvent) }); _path = Path.Combine(Path.GetTempPath(), "MessageStore", Guid.NewGuid().ToString()); if (!Directory.Exists(_path)) { Directory.CreateDirectory(_path); } _appendOnlyStore = new FileAppendOnlyStore(new DirectoryInfo(_path)); _appendOnlyStore.Initialize(); _messageStore = new MessageStore(_appendOnlyStore, _serializer); }
static IAppendOnlyStore CreateFileStoreForTesting() { var combine = Path.Combine(Directory.GetCurrentDirectory(), "store"); if (Directory.Exists(combine)) { Console.WriteLine(); Console.WriteLine("Wiping file event store for demo purposes."); Console.WriteLine("You can switch to Azure or SQL event stores by modifying Program.cs"); Console.WriteLine(); Directory.Delete(combine, true); } var store = new FileAppendOnlyStore(combine); store.Initialize(); return store; }
static IAppendOnlyStore CreateFileStoreForTesting() { var combine = Path.Combine(Directory.GetCurrentDirectory(), "store"); if (Directory.Exists(combine)) { Console.WriteLine(); Console.WriteLine("Wiping file event store for demo purposes."); Console.WriteLine("You can switch to Azure or SQL event stores by modifying Program.cs"); Console.WriteLine(); Directory.Delete(combine, true); } var store = new FileAppendOnlyStore(combine); store.Initialize(); return(store); }
public void SetUp() { _storeRecords = new List <StoreRecord>(); _serializer = new TestMessageSerializer(new[] { typeof(SerializerTest1), typeof(SerializerTest2), typeof(string) }); _path = Path.Combine(Path.GetTempPath(), "MessageStorePublisher", Guid.NewGuid().ToString()); _appendOnlyStore = new FileAppendOnlyStore(new DirectoryInfo(_path)); _appendOnlyStore.Initialize(); _store = new MessageStore(_appendOnlyStore, _serializer); var streamer = new EnvelopeStreamer(_serializer); var queueWriter = new TestQueueWriter(); _sender = new MessageSender(streamer, queueWriter); var store = new FileDocumentStore(Path.Combine(_path, "lokad-cqrs-test"), new DocumentStrategy()); _nuclearStorage = new NuclearStorage(store); _publisher = new MessageStorePublisher(_store, _sender, _nuclearStorage, DoWePublishThisRecord); }
public static ConsoleEnvironment Build() { var handler = new SynchronousEventHandler(); var inbox = new InboxProjection(); handler.RegisterHandler(inbox); //var store = new InMemoryStore(handler); var store = new FileAppendOnlyStore(new DirectoryInfo(Directory.GetCurrentDirectory())); store.Initialize(); var messageStore = new MessageStore(store); messageStore.LoadDataContractsFromAssemblyOf(typeof(ActionDefined)); var currentVersion = store.GetCurrentVersion(); var log = LogManager.GetLoggerFor<ConsoleEnvironment>(); log.Debug("Event Store ver {0}", currentVersion); if (currentVersion > 0) { log.Debug("Running in-memory replay"); foreach (var record in messageStore.EnumerateAllItems(0, int.MaxValue)) { foreach (var item in record.Items.OfType<Event>()) { handler.Handle(item); } } log.Debug("Replay complete"); } var events = new EventStore(messageStore,handler); var tenant = new TenantAppService(events, new RealTimeProvider()); var build = new ConsoleEnvironment { Store = events, Tenant = tenant, Commands = ConsoleCommands.Actions, Id = new TenantId(1), Inbox = inbox }; return build; }
public void SetUp() { _serializer = new TestMessageSerializer(new[] { typeof(SerializerTest1), typeof(SerializerTest2), typeof(string) }); _path = Path.Combine(Path.GetTempPath(), "MessageStore", Guid.NewGuid().ToString()); if (!Directory.Exists(_path)) { Directory.CreateDirectory(_path); } _appendOnlyStore = new FileAppendOnlyStore(new DirectoryInfo(_path)); var store = new MessageStore(_appendOnlyStore, _serializer); store.AppendToStore("stream1", MessageAttribute.Empty, -1, new[] { new SerializerTest1("msg1") }); store.AppendToStore("stream2", MessageAttribute.Empty, -1, new[] { new SerializerTest1("msg1"), new SerializerTest1("msg2") }); store.AppendToStore("stream3", MessageAttribute.Empty, -1, new[] { new SerializerTest1("msg1"), new SerializerTest1("msg2"), new SerializerTest1("msg3") }); store.RecordMessage("stream4", new ImmutableEnvelope("EnvId", DateTime.UtcNow, new SerializerTest1("msg1"), MessageAttribute.Empty)); _appendOnlyStore.Close(); _appendOnlyStore = new FileAppendOnlyStore(new DirectoryInfo(_path)); _appendOnlyStore.Initialize(); _store = new MessageStore(_appendOnlyStore, _serializer); }
static void Main() { // this Client App uses a standard "Windows Forms" application as its host Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); #region This WinForms host uses its own in-memory message bus to manage the UI... // It uses this in-memory bus to wire user-interface "UI" elements ("controls") to the // logic (in controllers) that will be triggered when the user interacts with those elements. // This allows us to send messages to the uiBus so that interested UI classes can // subscribe to the messages they care about, and react to them // when the bus publishes the messages to tell the UI controls what happened. #endregion var uiBus = new InMemoryBus("UI"); // .dat file to write Domain Events to this session var fileToStoreEventsIn = new FileAppendOnlyStore(new DirectoryInfo(Directory.GetCurrentDirectory())); fileToStoreEventsIn.Initialize(); // provide serialization stuff for our file storage var messageStore = new MessageStore(fileToStoreEventsIn); messageStore.LoadDataContractsFromAssemblyOf(typeof(ActionDefined)); // this WinForm App's own local file-based event storage var appEventStore = new AppEventStore(messageStore); #region Does App care about this msg? This class controls the App's "main message loop"... // It reads all msgs from in-memory queue (mainQueue below) and determines which messages // the App will/will not handle at a given time (based on specific app state). // For each queued message that it determines should be handled by // uiBus subscribers, it passes the messages through to our in-memory uiBus, // so bus subscribers can be called to react to the current message when the bus publishes it. #endregion var appController = new AppController(uiBus, appEventStore); #region In-memory structure that all events we defined will go through... // All domain & system messages we defined are captured // and accumulated in this queue until some code picks up // each message and processes it. // (ex: AppController, declared above, will do that processing in this case). #endregion var mainQueue = new QueuedHandler(appController, "Main Queue"); appController.SetMainQueue(mainQueue); appEventStore.SetDispatcher(mainQueue); var provider = new ClientPerspective(); ClientModelController.WireTo(appEventStore, provider, uiBus, mainQueue); // create services and bind them to the bus // we wire all controls together in a native way. // then we add adapters on top of that var form = new MainForm(); var navigation = new NavigationView(); form.NavigationRegion.RegisterDock(navigation, "nav"); form.NavigationRegion.SwitchTo("nav"); LogController.Wire(form, uiBus); #region View Controllers - Decoupling (UI) Views from their Controllers... // The intent with this design was to enable us to // write components or UI elements in a separated manner. // Provide the ability to develop new functionality independently and // it will sit in its own kind of "sandbox" so you can work on your stuff // without impacting everyone else. // It also sets us up for potential controller/code reuse and sharing in the future. // The UI is broken down into kinda "SEDA standalone controllers" // that communicate with each other via events. This event-driven // separation allows for cleanly implementing logic like: // "If the Inbox is selected, then only display these two menu items, // but if a project is displayed, then display these additional menu items." // See the Handle methods inside of MainFormController.cs for an example. // Event-centric approaches are one of the nicest ways to build // plug-in systems because plug-ins have services and contracts which are linked // to behaviors (and in our case, these are events). // Example: All CaptureThoughtController knows is that it gets handed a View // that it controls (CaptureThoughtForm) and then it has two other injections points, // a Bus and a MainQueue. // See CaptureThoughtController for more comments on how this design works. // The big idea here is that in the future, a controller can be passed an // INTERFACE (say, ICaptureThoughtForm) INSTEAD OF a concrete Windows Forms // implementation (CaptureThoughtForm) like it currently uses. // So we may have a WPF form in the future that implements ICaptureThoughtForm // and we could use that View implementation with the SAME CONTROLLER we already have. // Very similar to how you could use the MVVM pattern with MvvmCross to // reuse common code from the ViewModel down, but implement // platform-specific Views on top of that common/shared code. #endregion #region Wiring up our Views to Controllers... // A "Controller" or "Service" in this client-side ecosystem would usually // define at least two parameters: // MainQueue // and // "Bus" // MainQueue is the place where it would send events that happen inside of it. // Bus is what it subscribes to so that it will be called when specifc events happen. // "Wire" is a static method defined on these controllers that our setup // can call to let them know which form they control, // the bus they can use as a source to subscribe to UI events to react to, // and the target queue that they can use tell the rest of the world about events they generate. #endregion MainFormController.Wire(form, mainQueue, uiBus); AddStuffToInboxController.Wire(new AddStuffToInboxForm(form), uiBus, mainQueue); AddActionToProjectController.Wire(new AddActionToProjectForm(form),uiBus, mainQueue ); DefineProjectController.Wire(new DefineProjectForm(form), uiBus, mainQueue); InboxController.Wire(form.MainRegion, mainQueue, uiBus, provider); NavigationController.Wire(navigation, mainQueue, uiBus, provider); ProjectController.Wire(form.MainRegion, mainQueue, uiBus, provider); NavigateBackController.Wire(uiBus, mainQueue, form); mainQueue.Enqueue(new AppInit()); mainQueue.Start(); Application.Run(form); }
public static void WireControlLogic(UserInterface ui) { #region This WinForms host uses its own in-memory message bus to manage the UI... // It uses this in-memory bus to wire user-interface "UI" elements ("controls") to the // logic (in controllers) that will be triggered when the user interacts with those elements. // This allows us to send messages to the uiBus so that interested UI classes can // subscribe to the messages they care about, and react to them // when the bus publishes the messages to tell the UI controls what happened. #endregion var uiBus = new InMemoryBus("UI"); // .dat file to write Domain Events to this session var fileToStoreEventsIn = new FileAppendOnlyStore(new DirectoryInfo(Directory.GetCurrentDirectory())); fileToStoreEventsIn.Initialize(); // provide serialization stuff for our file storage var messageStore = new MessageStore(fileToStoreEventsIn); messageStore.LoadDataContractsFromAssemblyOf(typeof(ActionDefined)); // this WinForm App's own local file-based event storage var appEventStore = new AppEventStore(messageStore); #region Does App care about this msg? This class controls the App's "main message loop"... // It reads all msgs from in-memory queue (mainQueue below) and determines which messages // the App will/will not handle at a given time (based on specific app state). // For each queued message that it determines should be handled by // uiBus subscribers, it passes the messages through to our in-memory uiBus, // so bus subscribers can be called to react to the current message when the bus publishes it. #endregion var appController = new AppController(uiBus, appEventStore); #region In-memory structure that all events we defined will go through... // All domain & system messages we defined are captured // and accumulated in this queue until some code picks up // each message and processes it. // (ex: AppController, declared above, will do that processing in this case). #endregion var mainQueue = new QueuedHandler(appController, "Main Queue"); appController.SetMainQueue(mainQueue); appEventStore.SetDispatcher(mainQueue); var provider = new ClientPerspective(); ClientModelController.WireTo(appEventStore, provider, uiBus, mainQueue); // create services and bind them to the bus // we wire all controls together in a native way. // then we add adapters on top of that LogController.Wire(ui.Log, uiBus); #region View Controllers - Decoupling (UI) Views from their Controllers... // The intent with this design was to enable us to // write components or UI elements in a separated manner. // Provide the ability to develop new functionality independently and // it will sit in its own kind of "sandbox" so you can work on your stuff // without impacting everyone else. // It also sets us up for potential controller/code reuse and sharing in the future. // The UI is broken down into kinda "SEDA standalone controllers" // that communicate with each other via events. This event-driven // separation allows for cleanly implementing logic like: // "If the Inbox is selected, then only display these two menu items, // but if a project is displayed, then display these additional menu items." // See the Handle methods inside of MainFormController.cs for an example. // Event-centric approaches are one of the nicest ways to build // plug-in systems because plug-ins have services and contracts which are linked // to behaviors (and in our case, these are events). // Example: All CaptureThoughtController knows is that it gets handed a View // that it controls (CaptureThoughtForm) and then it has two other injections points, // a Bus and a MainQueue. // See CaptureThoughtController for more comments on how this design works. // The big idea here is that in the future, a controller can be passed an // INTERFACE (say, ICaptureThoughtForm) INSTEAD OF a concrete Windows Forms // implementation (CaptureThoughtForm) like it currently uses. // So we may have a WPF form in the future that implements ICaptureThoughtForm // and we could use that View implementation with the SAME CONTROLLER we already have. // Very similar to how you could use the MVVM pattern with MvvmCross to // reuse common code from the ViewModel down, but implement // platform-specific Views on top of that common/shared code. #endregion #region Wiring up our Views to Controllers... // A "Controller" or "Service" in this client-side ecosystem would usually // define at least two parameters: // MainQueue // and // "Bus" // MainQueue is the place where it would send events that happen inside of it. // Bus is what it subscribes to so that it will be called when specifc events happen. // "Wire" is a static method defined on these controllers that our setup // can call to let them know which form they control, // the bus they can use as a source to subscribe to UI events to react to, // and the target queue that they can use tell the rest of the world about events they generate. #endregion MainMenuController.Wire(ui.Menu, mainQueue, uiBus); AddStuffToInboxController.Wire(ui.AddStuffToInboxWizard, uiBus, mainQueue); AddActionToProjectController.Wire(ui.AddActionToProjectWizard, uiBus, mainQueue); DefineProjectController.Wire(ui.DefineProjectWizard, uiBus, mainQueue); InboxController.Wire(ui.InboxView, mainQueue, uiBus, provider); NavigationController.Wire(ui.Navigation, mainQueue, uiBus, provider); ProjectController.Wire(ui.ProjectView, mainQueue, uiBus, provider); NavigateBackController.Wire(uiBus, mainQueue, ui.BackView); mainQueue.Enqueue(new AppInit()); mainQueue.Start(); }