Skip to content

Commit

Permalink
Event more attributes about network objects when they are registered (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lyonsil authored Jan 9, 2024
1 parent c752f0b commit d404d51
Show file tree
Hide file tree
Showing 17 changed files with 421 additions and 57 deletions.
12 changes: 9 additions & 3 deletions c-sharp/Messages/MessageEventObjectCreated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,26 @@ public sealed class MessageEventObjectCreated
private MessageEventObjectCreated()
: base(Messages.EventType.OBJECT_CREATE, null!) { }

public MessageEventObjectCreated(string id, string[] functions)
public MessageEventObjectCreated(string id, string objectType, string[] functions)
: base(
Messages.EventType.OBJECT_CREATE,
new MessageEventObjectCreatedContents { Id = id, Functions = functions }
new MessageEventObjectCreatedContents
{
Id = id,
ObjectType = objectType,
Functions = functions
}
) { }
}

public sealed record MessageEventObjectCreatedContents
{
public string? Id { get; set; }
public string? ObjectType { get; set; }
public string[]? Functions { get; set; }

public override string ToString()
{
return $"Id = {Id}, Functions = {(Functions != null ? string.Join(',', Functions) : "[null]")}";
return $"Id = {Id}, ObjectType = {ObjectType}, Functions = {(Functions != null ? string.Join(',', Functions) : "[null]")}";
}
}
64 changes: 64 additions & 0 deletions c-sharp/Messages/MessageEventProjectDataProviderCreated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using Paranext.DataProvider.JsonUtils;

namespace Paranext.DataProvider.Messages;

[JsonMessageDeserialization(
MessageField.MESSAGE_TYPE,
MessageType.EVENT,
MessageField.EVENT_TYPE,
Messages.EventType.OBJECT_CREATE,
MessageField.OBJECT_TYPE,
NetworkObjectType.PROJECT_DATA_PROVIDER
)]
public sealed class MessageEventProjectDataProviderCreated
: MessageEventGeneric<MessageEventProjectDataProviderCreatedContents>
{
/// <summary>
/// ONLY FOR DESERIALIZATION
/// </summary>
private MessageEventProjectDataProviderCreated()
: base(Messages.EventType.OBJECT_CREATE, null!) { }

public MessageEventProjectDataProviderCreated(
string id,
string[] functions,
string projectID,
string projectType,
string projectStorageInterpreterId
)
: base(
Messages.EventType.OBJECT_CREATE,
new MessageEventProjectDataProviderCreatedContents
{
Id = id,
ObjectType = NetworkObjectType.PROJECT_DATA_PROVIDER,
Functions = functions,
Attributes = new ProjectDataProviderAttributes
{
ProjectId = projectID,
ProjectType = projectType,
ProjectStorageInterpreterId = projectStorageInterpreterId
}
}
) { }
}

public sealed record MessageEventProjectDataProviderCreatedContents
{
public string? Id { get; set; }
public string? ObjectType { get; set; }
public string[]? Functions { get; set; }
public ProjectDataProviderAttributes? Attributes { get; set; }

public override string ToString()
{
return $"Id = {Id}, ObjectType = {ObjectType}, Functions = {(Functions != null ? string.Join(',', Functions) : "[null]")}, ProjectID = {Attributes?.ProjectId}, ProjectType = {Attributes?.ProjectType}, ProjectStorageInterpreterId = {Attributes?.ProjectStorageInterpreterId}";
}
}

public sealed record ProjectDataProviderAttributes
{
public string? ProjectId { get; set; }
public string? ProjectType { get; set; }
public string? ProjectStorageInterpreterId { get; set; }
}
55 changes: 55 additions & 0 deletions c-sharp/Messages/MessageEventProjectDataProviderFactoryCreated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using Paranext.DataProvider.JsonUtils;

namespace Paranext.DataProvider.Messages;

[JsonMessageDeserialization(
MessageField.MESSAGE_TYPE,
MessageType.EVENT,
MessageField.EVENT_TYPE,
Messages.EventType.OBJECT_CREATE,
MessageField.OBJECT_TYPE,
NetworkObjectType.PROJECT_DATA_PROVIDER_FACTORY
)]
public sealed class MessageEventProjectDataProviderFactoryCreated
: MessageEventGeneric<MessageEventProjectDataProviderFactoryCreatedContents>
{
/// <summary>
/// ONLY FOR DESERIALIZATION
/// </summary>
private MessageEventProjectDataProviderFactoryCreated()
: base(Messages.EventType.OBJECT_CREATE, null!) { }

public MessageEventProjectDataProviderFactoryCreated(
string id,
string[] functions,
string projectType
)
: base(
Messages.EventType.OBJECT_CREATE,
new MessageEventProjectDataProviderFactoryCreatedContents
{
Id = id,
ObjectType = NetworkObjectType.PROJECT_DATA_PROVIDER,
Functions = functions,
Attributes = new ProjectDataProviderFactoryAttributes { ProjectType = projectType }
}
) { }
}

public sealed record MessageEventProjectDataProviderFactoryCreatedContents
{
public string? Id { get; set; }
public string? ObjectType { get; set; }
public string[]? Functions { get; set; }
public ProjectDataProviderFactoryAttributes? Attributes { get; set; }

public override string ToString()
{
return $"Id = {Id}, ObjectType = {ObjectType}, Functions = {(Functions != null ? string.Join(',', Functions) : "[null]")}, ProjectType = {Attributes?.ProjectType}";
}
}

public sealed record ProjectDataProviderFactoryAttributes
{
public string? ProjectType { get; set; }
}
61 changes: 61 additions & 0 deletions c-sharp/Messages/MessageEventProjectStorageInterpreterCreated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using Paranext.DataProvider.JsonUtils;

namespace Paranext.DataProvider.Messages;

[JsonMessageDeserialization(
MessageField.MESSAGE_TYPE,
MessageType.EVENT,
MessageField.EVENT_TYPE,
Messages.EventType.OBJECT_CREATE,
MessageField.OBJECT_TYPE,
NetworkObjectType.PROJECT_STORAGE_INTERPRETER
)]
public sealed class MessageEventProjectStorageInterpreterCreated
: MessageEventGeneric<MessageEventProjectStorageInterpreterCreatedContents>
{
/// <summary>
/// ONLY FOR DESERIALIZATION
/// </summary>
private MessageEventProjectStorageInterpreterCreated()
: base(Messages.EventType.OBJECT_CREATE, null!) { }

public MessageEventProjectStorageInterpreterCreated(
string id,
string[] functions,
string projectStorageType,
string[] projectTypes
)
: base(
Messages.EventType.OBJECT_CREATE,
new MessageEventProjectStorageInterpreterCreatedContents
{
Id = id,
ObjectType = NetworkObjectType.PROJECT_STORAGE_INTERPRETER,
Functions = functions,
Attributes = new ProjectStorageInterpreterAttributes
{
ProjectStorageType = projectStorageType,
ProjectTypes = projectTypes
}
}
) { }
}

public sealed record MessageEventProjectStorageInterpreterCreatedContents
{
public string? Id { get; set; }
public string? ObjectType { get; set; }
public string[]? Functions { get; set; }
public ProjectStorageInterpreterAttributes? Attributes { get; set; }

public override string ToString()
{
return $"Id = {Id}, ObjectType = {ObjectType}, Functions = {(Functions != null ? string.Join(',', Functions) : "[null]")}, ProjectStorageType = {Attributes?.ProjectStorageType}, ProjectType = {Attributes?.ProjectTypes}";
}
}

public sealed record ProjectStorageInterpreterAttributes
{
public string? ProjectStorageType { get; set; }
public string[]? ProjectTypes { get; set; }
}
1 change: 1 addition & 0 deletions c-sharp/Messages/MessageField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ internal static class MessageField
{
public const string MESSAGE_TYPE = "type";
public const string EVENT_TYPE = "eventType";
public const string OBJECT_TYPE = "objectType";
}
10 changes: 10 additions & 0 deletions c-sharp/Messages/NetworkObjectType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Paranext.DataProvider.Messages;

public static class NetworkObjectType
{
public const string DATA_PROVIDER = "dataProvider";
public const string OBJECT = "object";
public const string PROJECT_DATA_PROVIDER_FACTORY = "pdpFactory";
public const string PROJECT_DATA_PROVIDER = "pdp";
public const string PROJECT_STORAGE_INTERPRETER = "psi";
}
36 changes: 34 additions & 2 deletions c-sharp/NetworkObjects/DataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,42 @@ public MessageEventDataUpdated(string eventType, object dataScope)
private readonly ConcurrentDictionary<string, MessageEventDataUpdated> _updateEventsByScope =
new();

protected DataProvider(string name, PapiClient papiClient)
protected DataProvider(
string name,
PapiClient papiClient,
string dataProviderType = NetworkObjectType.DATA_PROVIDER
)
: base(papiClient)
{
// "-data" is the suffix used by PAPI for data provider names
DataProviderName = name + "-data";

DataProviderType = dataProviderType;

// "onDidUpdate" is the event name used by PAPI for data providers to notify consumers of updates
_eventType = $"{DataProviderName}:onDidUpdate";
}

/// <summary>
/// Name/ID of the data provider as registered on the network
/// </summary>
public string DataProviderName { get; }

/// <summary>
/// Data provider type to be shared on the network
/// </summary>
public string DataProviderType { get; }

/// <summary>
/// Register this data provider on the network so that other services can use it
/// </summary>
public async Task RegisterDataProvider()
{
await RegisterNetworkObject(DataProviderName, GetFunctionNames(), FunctionHandler);
await RegisterNetworkObject(
DataProviderName,
GetDataProviderCreatedEvent(),
FunctionHandler
);
await StartDataProvider();
}

Expand Down Expand Up @@ -73,6 +91,20 @@ private ResponseToRequest FunctionHandler(JsonElement request)
return HandleRequest(functionName, jsonArray);
}

/// <summary>
/// Create an event that tells the network details about the data provider that is being created
/// </summary>
protected virtual MessageEvent GetDataProviderCreatedEvent()
{
var functionNames = GetFunctionNames();
functionNames.Sort();
return new MessageEventObjectCreated(
DataProviderName,
DataProviderType,
functionNames.ToArray()
);
}

/// <summary>
/// Notify all processes on the network that this data provider has new data.
///
Expand Down
22 changes: 8 additions & 14 deletions c-sharp/NetworkObjects/NetworkObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Paranext.DataProvider.NetworkObjects;

internal abstract class NetworkObject
{
private string[] _networkObjectFunctionNames = Array.Empty<string>();
private MessageEvent? _registrationEvent = null;

protected NetworkObject(PapiClient papiClient)
{
Expand All @@ -18,22 +18,19 @@ protected NetworkObject(PapiClient papiClient)

/// <summary>
/// Notify PAPI services we have a new network object they can use
/// TODO: Use reflection (and attributes?) to get the function names supported. When doing this work, might as well call the functions using the same mechanism.
/// </summary>
/// <param name="networkObjectName">Services access this network object using this name</param>
/// <param name="functionNames">List of function names that should be provided in the object creation notification</param>
/// <param name="registrationEvent">Event for notifying the network that the object was registered</param>
/// <param name="requestHandler">Function that will handle calls from services to this network object</param>
/// <exception cref="Exception">Throws if the network object could not be registered properly</exception>
protected async Task RegisterNetworkObject(
string networkObjectName,
List<string> functionNames,
MessageEvent registrationEvent,
Func<JsonElement, ResponseToRequest> requestHandler
)
{
if (_networkObjectFunctionNames.Length > 0)
if (_registrationEvent != null)
throw new Exception($"{networkObjectName} has already been registered on the network");
if (functionNames.Count == 0)
throw new ArgumentException($"Must provide function names for {networkObjectName}");

// PAPI requires network objects to expose "get" and "function" requests
var getReqType = $"object:{networkObjectName}.get";
Expand All @@ -46,16 +43,13 @@ Func<JsonElement, ResponseToRequest> requestHandler
throw new Exception($"Could not register FUNCTION for {networkObjectName}");

// Notify the network that we registered this network object
functionNames.Sort();
_networkObjectFunctionNames = functionNames.ToArray();
PapiClient.SendEvent(
new MessageEventObjectCreated(networkObjectName, _networkObjectFunctionNames)
);
_registrationEvent = registrationEvent;
PapiClient.SendEvent(registrationEvent);
}

private ResponseToRequest HandleGet(JsonElement getRequest)
{
// Respond that this network object exists along with its function list
return ResponseToRequest.Succeeded(new List<string>(_networkObjectFunctionNames));
// Respond that this network object exists along with its registration details
return ResponseToRequest.Succeeded(_registrationEvent);
}
}
5 changes: 5 additions & 0 deletions c-sharp/Projects/ParatextProjectDataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ protected override Task StartDataProvider()
return Task.CompletedTask;
}

protected override string GetProjectStorageInterpreterId()
{
return _paratextPsi.DataProviderName;
}

protected override ResponseToRequest GetExtensionData(ProjectDataScope dataScope)
{
return _paratextPsi.GetExtensionData(dataScope);
Expand Down
Loading

0 comments on commit d404d51

Please sign in to comment.