-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
// <copyright file="AbstractTxModel.cs" company="Devexperts LLC"> | ||
// Copyright © 2024 Devexperts LLC. All rights reserved. | ||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. | ||
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// </copyright> | ||
|
||
using System; | ||
using DxFeed.Graal.Net.Api; | ||
using DxFeed.Graal.Net.Events; | ||
using DxFeed.Graal.Net.Native.Model; | ||
|
||
namespace DxFeed.Graal.Net.Models; | ||
|
||
/// <summary> | ||
/// Abstract base class for models that handle transactions of <see cref="IIndexedEvent"/>. | ||
/// This class manages all snapshot and transaction logic, subscription handling, and listener notifications. | ||
/// </summary> | ||
/// <remarks> | ||
/// This model is designed to handle incremental transactions. Users of this model only see the list | ||
/// of events in a consistent state. This model delays incoming events that are part of an incomplete snapshot | ||
/// or ongoing transaction until the snapshot is complete or the transaction has ended. | ||
/// | ||
/// <h3>Configuration</h3> | ||
/// This model must be configured using the <see cref="Builder{TB,TM}"/>. Specific implementations can add additional | ||
/// configuration options as needed. | ||
/// | ||
/// <h3>Resource management and closed models</h3> | ||
/// Attached model is a potential memory leak. If the pointer to attached model is lost, then there is no way | ||
/// to detach this model from the feed and the model will not be reclaimed by the garbage collector as long as the | ||
/// corresponding feed is still used. Detached model can be reclaimed by the garbage collector, but detaching model | ||
/// requires knowing the pointer to the feed at the place of the call, which is not always convenient. | ||
/// | ||
/// The convenient way to detach model from the feed is to call its <see cref="Close"/> method. Closed model | ||
/// becomes permanently detached from all feeds, removes all its listeners and is guaranteed to be reclaimable by | ||
/// the garbage collector as soon as all external references to it are cleared. | ||
/// | ||
/// <h3>Threads and locks</h3> | ||
/// This class is thread-safe and can be used concurrently from multiple threads without external synchronization. | ||
/// </remarks> | ||
public abstract class AbstractTxModel | ||
{ | ||
private protected readonly AbstractTxModelHandle handle; | ||
|
||
private protected AbstractTxModel(AbstractTxModelHandle handle) => | ||
this.handle = handle; | ||
|
||
/// <summary> | ||
/// Gets whether batch processing is enabled. | ||
/// See <see cref="Builder{TB,TM}.WithBatchProcessing(bool)"/>. | ||
/// </summary> | ||
/// <returns> | ||
/// <c>true</c> if batch processing is enabled; otherwise, <c>false</c>. | ||
/// </returns> | ||
public bool IsBatchProcessing() => | ||
handle.IsBatchProcessing(); | ||
|
||
/// <summary> | ||
/// Gets whether snapshot processing is enabled. | ||
/// See <see cref="Builder{TB,TM}.WithSnapshotProcessing(bool)"/>. | ||
/// </summary> | ||
/// <returns> | ||
/// <c>true</c> if snapshot processing is enabled; otherwise, <c>false</c>. | ||
/// </returns> | ||
public bool IsSnapshotProcessing() => | ||
handle.IsSnapshotProcessing(); | ||
|
||
/// <summary> | ||
/// Closes this model and makes it <i>permanently detached</i>. | ||
/// </summary> | ||
/// <remarks> | ||
/// This method clears installed listeners and ensures that the model | ||
/// can be safely garbage-collected when all outside references to it are lost. | ||
/// </remarks> | ||
public void Close() => | ||
handle.Close(); | ||
|
||
/// <summary> | ||
/// Abstract builder for building models inherited from <see cref="AbstractTxModel"/>. | ||
/// Specific implementations can add additional configuration options to this builder. | ||
/// </summary> | ||
/// <remarks> | ||
/// Inheritors of this class must override the abstract method <see cref="Build"/> to build a specific model. | ||
/// </remarks> | ||
/// <typeparam name="TB">The type of the builder subclass.</typeparam> | ||
/// <typeparam name="TM">The type of the model subclass.</typeparam> | ||
public abstract class Builder<TB, TM> | ||
where TB : Builder<TB, TM> | ||
where TM : AbstractTxModel | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Builder{TB, TM}"/> class with the specified event type. | ||
/// </summary> | ||
/// <param name="eventType">The type of events processed by the model being created.</param> | ||
protected Builder(Type eventType) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Enables or disables batch processing. <b>This is enabled by default</b>. | ||
/// </summary> | ||
/// <remarks> | ||
/// If batch processing is disabled, the model will notify the listener | ||
/// <b>separately for each transaction</b> (even if it is represented by a single event); | ||
/// otherwise, transactions can be combined in a single listener call. | ||
/// | ||
/// <br/>A transaction may represent either a snapshot or update events that are received after a snapshot. | ||
/// Whether this flag is set or not, the model will always notify listeners that a snapshot has been received | ||
/// and will not combine multiple snapshots or a snapshot with another transaction | ||
/// into a single listener notification. | ||
/// </remarks> | ||
/// <param name="isBatchProcessing"><c>true</c> to enable batch processing; <c>false</c> otherwise.</param> | ||
/// <returns>The builder instance.</returns> | ||
public TB WithBatchProcessing(bool isBatchProcessing) | ||
{ | ||
return (TB)this; | ||
} | ||
|
||
/// <summary> | ||
/// Enables or disables snapshot processing. <b>This is disabled by default</b>. | ||
/// </summary> | ||
/// <remarks> | ||
/// If snapshot processing is enabled, transactions representing a snapshot will be processed as follows: | ||
/// events that are marked for removal will be removed, repeated indexes will be merged, and | ||
/// event flags of events are set to zero; otherwise, the user will see the snapshot in raw form, | ||
/// with possible repeated indexes, events marked for removal, and event flags unchanged. | ||
/// | ||
/// Whether this flag is set or not, in transactions that are not a snapshot, events that are marked | ||
/// for removal will not be removed, repeated indexes will not be merged, and | ||
/// event flags of events will not be changed. | ||
/// This flag only affects the processing of transactions that are a snapshot. | ||
/// </remarks> | ||
/// <param name="isSnapshotProcessing"><c>true</c> to enable snapshot processing; <c>false</c> otherwise.</param> | ||
/// <returns>The builder instance.</returns> | ||
public TB WithSnapshotProcessing(bool isSnapshotProcessing) | ||
{ | ||
return (TB)this; | ||
} | ||
|
||
/// <summary> | ||
/// Sets the <see cref="DXFeed"/> for the model being created. | ||
/// The feed cannot be attached after the model has been built. | ||
/// </summary> | ||
/// <param name="feed">The <see cref="DXFeed"/>.</param> | ||
/// <returns>The builder instance.</returns> | ||
public TB WithFeed(DXFeed feed) | ||
{ | ||
return (TB)this; | ||
} | ||
|
||
/// <summary> | ||
/// Sets the subscription symbol for the model being created. | ||
/// The symbol cannot be added or changed after the model has been built. | ||
/// </summary> | ||
/// <param name="symbol">The subscription symbol.</param> | ||
/// <returns>The builder instance.</returns> | ||
public TB WithSymbol(object symbol) | ||
{ | ||
return (TB)this; | ||
} | ||
|
||
/// <summary> | ||
/// Sets the listener for transaction notifications. | ||
/// The listener cannot be changed or added once the model has been built. | ||
/// </summary> | ||
/// <param name="listener">The transaction listener.</param> | ||
/// <returns>The builder instance.</returns> | ||
public TB WithListener(TxModelListener listener) | ||
{ | ||
return (TB)this; | ||
} | ||
|
||
/// <summary> | ||
/// Builds an instance of the model based on the provided parameters. | ||
/// </summary> | ||
/// <returns>The created model.</returns> | ||
public abstract TM Build(); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
// <copyright file="IndexedTxModel.cs" company="Devexperts LLC"> | ||
// Copyright © 2024 Devexperts LLC. All rights reserved. | ||
// This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. | ||
// If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||
// </copyright> | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using DxFeed.Graal.Net.Api; | ||
using DxFeed.Graal.Net.Events; | ||
using DxFeed.Graal.Net.Native.Model; | ||
|
||
namespace DxFeed.Graal.Net.Models; | ||
|
||
/// <summary> | ||
/// An incremental model for indexed events. | ||
/// This model manages all snapshot and transaction logic, subscription handling, and listener notifications. | ||
/// </summary> | ||
/// <remarks> | ||
/// <para> | ||
/// This model is designed to handle incremental transactions. Users of this model only see the list | ||
/// of events in a consistent state. This model delays incoming events that are part of an incomplete snapshot | ||
/// or ongoing transaction until the snapshot is complete or the transaction has ended. This model notifies | ||
/// the user of received transactions through an installed <see cref="TxModelListener"/> listener. | ||
/// </para> | ||
/// <h3>Configuration</h3> | ||
/// <para> | ||
/// This model must be configured using the <see cref="Builder"/> class, as most configuration | ||
/// settings cannot be changed once the model is built. This model requires configuration with | ||
/// a <see cref="Builder.WithSymbol(object)"/> symbol and | ||
Check warning on line 30 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on win-x64
Check warning on line 30 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on win-x64
Check warning on line 30 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on linux-x64
Check warning on line 30 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on linux-x64
Check warning on line 30 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on osx-arm64
|
||
/// a <see cref="Builder.WithSources(DxFeed.Graal.Net.Events.IndexedEventSource[])"/> sources | ||
/// for subscription, and it must be <see cref="Builder.WithFeed(DXFeed)"/> attached to a <see cref="DXFeed"/> | ||
Check warning on line 32 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on win-x64
Check warning on line 32 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on win-x64
Check warning on line 32 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on linux-x64
Check warning on line 32 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on linux-x64
Check warning on line 32 in src/DxFeed.Graal.Net/Models/IndexedTxModel.cs GitHub Actions / Build & Test on osx-arm64
|
||
/// instance to begin operation. | ||
/// For ease of use, some of these configurations can be changed after the model is built, see | ||
/// <see cref="SetSources(DxFeed.Graal.Net.Events.IndexedEventSource[])"/>. | ||
/// </para> | ||
/// <para> | ||
/// This model only supports single symbol subscriptions; multiple symbols cannot be configured. | ||
/// </para> | ||
/// <h3>Resource management and closed models</h3> | ||
/// <para> | ||
/// Attached model is a potential memory leak. If the pointer to attached model is lost, then there is no way | ||
/// to detach this model from the feed and the model will not be reclaimed by the garbage collector as long as the | ||
/// corresponding feed is still used. Detached model can be reclaimed by the garbage collector, but detaching model | ||
/// requires knowing the pointer to the feed at the place of the call, which is not always convenient. | ||
/// </para> | ||
/// <para> | ||
/// The convenient way to detach model from the feed is to call its <see cref="AbstractTxModel.Close"/> method. | ||
/// Closed model becomes permanently detached from all feeds, removes all its listeners and is guaranteed | ||
/// to be reclaimable by the garbage collector as soon as all external references to it are cleared. | ||
/// </para> | ||
/// <h3>Threads and locks</h3> | ||
/// <para> | ||
/// This class is thread-safe and can be used concurrently from multiple threads without external synchronization. | ||
/// </para> | ||
/// </remarks> | ||
public sealed class IndexedTxModel : AbstractTxModel | ||
{ | ||
private IndexedTxModel(AbstractTxModelHandle handle) | ||
: base(handle) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Factory method to create a new builder for this model. | ||
/// </summary> | ||
/// <param name="eventType">The class type of the time series event.</param> | ||
/// <returns>A new <see cref="Builder"/> instance.</returns> | ||
public static Builder NewBuilder(Type eventType) => | ||
new(eventType); | ||
|
||
/// <summary> | ||
/// Returns the current set of sources. | ||
/// If no sources have been set, an empty set is returned, | ||
/// indicating that all possible sources have been subscribed to. | ||
/// </summary> | ||
/// <returns>The set of current sources.</returns> | ||
public HashSet<IndexedEventSource> GetSources() => | ||
((IndexedTxModelHandle)handle).GetSources(); | ||
|
||
/// <summary> | ||
/// Sets the sources from which to subscribe for indexed events. | ||
/// If an empty list is provided, subscriptions will default to all available sources. | ||
/// If these sources have already been set, nothing happens. | ||
/// </summary> | ||
/// <param name="sources">The specified sources.</param> | ||
public void SetSources(params IndexedEventSource[] sources) => | ||
((IndexedTxModelHandle)handle).SetSources(sources); | ||
|
||
/// <summary> | ||
/// Sets the sources from which to subscribe for indexed events. | ||
/// If an empty set is provided, subscriptions will default to all available sources. | ||
/// If these sources have already been set, nothing happens. | ||
/// </summary> | ||
/// <param name="sources">The specified sources.</param> | ||
public void SetSources(ICollection<IndexedEventSource> sources) => | ||
((IndexedTxModelHandle)handle).SetSources(sources); | ||
|
||
/// <summary> | ||
/// A builder class for creating an instance of <see cref="IndexedTxModel"/>. | ||
/// </summary> | ||
public class Builder : Builder<Builder, IndexedTxModel> | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="Builder"/> class with the specified event type. | ||
/// </summary> | ||
/// <param name="eventType">The type of events processed by the model being created.</param> | ||
public Builder(Type eventType) | ||
: base(eventType) | ||
{ | ||
} | ||
|
||
/// <summary> | ||
/// Sets the sources from which to subscribe for indexed events. | ||
/// If no sources have been set, subscriptions will default to all possible sources. | ||
/// </summary> | ||
/// <remarks> | ||
/// The default value for this source is an empty set, | ||
/// which means that this model subscribes to all available sources. | ||
/// These sources can be changed later, after the model has been created, | ||
/// by calling <see cref="SetSources(IndexedEventSource[])"/>. | ||
/// </remarks> | ||
/// <param name="sources">The specified sources.</param> | ||
/// <returns>The builder instance.</returns> | ||
public Builder WithSources(params IndexedEventSource[] sources) | ||
{ | ||
return this; | ||
} | ||
|
||
/// <summary> | ||
/// Sets the sources from which to subscribe for indexed events. | ||
/// If no sources have been set, subscriptions will default to all possible sources. | ||
/// </summary> | ||
/// <remarks> | ||
/// The default value for this source is an empty set, | ||
/// which means that this model subscribes to all available sources. | ||
/// These sources can be changed later, after the model has been created, | ||
/// by calling <see cref="SetSources(IndexedEventSource[])"/>. | ||
/// </remarks> | ||
/// <param name="sources">The specified sources.</param> | ||
/// <returns>The builder instance.</returns> | ||
public Builder WithSources(ICollection<IndexedEventSource> sources) | ||
{ | ||
return this; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public override IndexedTxModel Build() => | ||
throw new NotImplementedException(); | ||
} | ||
} |