Skip to content

Commit

Permalink
Fix Scripture update events not causing data providers to re-fetch da…
Browse files Browse the repository at this point in the history
…ta (#644)
  • Loading branch information
tjcouch-sil authored Nov 15, 2023
2 parents 6dd7202 + 039c303 commit efd9c11
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 23 deletions.
8 changes: 4 additions & 4 deletions c-sharp-tests/Projects/ParatextDataProviderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public async Task GetFunctions_MissingParameter(string function)
await provider.RegisterDataProvider();

JsonElement serverMessage = CreateRequestMessage(function);

Enum<RequestType> requestType = new(PdpDataRequest);
Message result = Client.FakeMessageFromServer(new MessageRequest(requestType, requesterId, serverMessage)).First();

Expand All @@ -66,7 +66,7 @@ public async Task GetFunctions_InvalidParameters(string function, int bookNum, i

JsonElement serverMessage =
CreateRequestMessage(function, CreateVerseRefNode(bookNum, chapterNum, verseNum));

Enum<RequestType> requestType = new(PdpDataRequest);
Message result = Client.FakeMessageFromServer(new MessageRequest(requestType, requesterId, serverMessage)).First();

Expand Down Expand Up @@ -132,7 +132,7 @@ public async Task SetChapterUsx_ValidResults(int bookNum, int chapterNum, int ve
Enum<RequestType> requestType = new(PdpDataRequest);
Message result = Client.FakeMessageFromServer(new MessageRequest(requestType, requesterId, serverMessage)).First();

VerifyResponse(result, null, requestType, requesterId, "ChapterUSX");
VerifyResponse(result, null, requestType, requesterId, ParatextProjectStorageInterpreter.AllScriptureDataTypes);

// Verify the new text was saved to disk
VerseRef reference = new(bookNum, chapterNum, verseNum, _scrText.Settings.Versification);
Expand Down Expand Up @@ -168,7 +168,7 @@ public async Task SetChapterUsfm_ValidResults(int bookNum, int chapterNum, int v
Enum<RequestType> requestType = new(PdpDataRequest);
Message result = Client.FakeMessageFromServer(new MessageRequest(requestType, requesterId, serverMessage)).First();

VerifyResponse(result, null, requestType, requesterId, "ChapterUSFM");
VerifyResponse(result, null, requestType, requesterId, ParatextProjectStorageInterpreter.AllScriptureDataTypes);

// Verify the new text was saved to disk
VerseRef reference = new(bookNum, chapterNum, verseNum, _scrText.Settings.Versification);
Expand Down
58 changes: 42 additions & 16 deletions c-sharp/NetworkObjects/DataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ namespace Paranext.DataProvider.NetworkObjects;
internal abstract class DataProvider : NetworkObject
{
// This is an internal class because nothing else should be instantiating it directly
private class MessageEventDataUpdated : MessageEventGeneric<string>
private class MessageEventDataUpdated : MessageEventGeneric<object>
{
// A parameterless constructor is required for serialization to work
// ReSharper disable once UnusedMember.Local
public MessageEventDataUpdated()
: base(Enum<EventType>.Null) { }

public MessageEventDataUpdated(Enum<EventType> eventType, string dataScope)
public MessageEventDataUpdated(Enum<EventType> eventType, object dataScope)
: base(eventType, dataScope) { }
}

Expand Down Expand Up @@ -76,37 +76,63 @@ private ResponseToRequest FunctionHandler(dynamic? request)
}

/// <summary>
/// Notify all processes on the network that this data provider has new data
/// Notify all processes on the network that this data provider has new data.
///
/// This method transforms the data scope in the same way that `data-provider`service.ts`'s
/// `mapUpdateInstructionsToUpdateEvent` does
/// </summary>
/// <param name="dataScope">Indicator of what data changed in the provider</param>
/// <param name="dataScope">Indicator of what data changed in the provider. Can be '*' for all
/// updates, a `string` to update one data type, or a `List<string>` of data types to update. If dataScope is null, nothing happens. </param>
protected void SendDataUpdateEvent(dynamic? dataScope)
{
string scopeString;
// The final computed data scope to send out in the update event. Based on dataScope
object dataScopeResult;

if ((dataScope is string s) && !string.IsNullOrWhiteSpace(s))
{
// If we are returning "*", just pass it as a string. Otherwise we have to provide a JSON list of strings.
// If we are returning "*", just pass it as a string. Otherwise we have to provide a list of strings.
// Presumably this will change as part of https://github.com/paranext/paranext-core/issues/443
scopeString = (s == "*") ? s : JsonConvert.SerializeObject(new List<string> { s });
dataScopeResult = (s == "*") ? s : new List<string> { s };
}
else if (dataScope != null)
else if (dataScope is List<string> dataScopeList)
{
try
if (dataScopeList.Count > 0)
dataScopeResult = dataScope;
// Empty list means no data type updates
else
{
scopeString = JsonConvert.SerializeObject(dataScope);
}
catch (Exception ex)
{
Console.WriteLine($"Unable to send data update event: {ex}");
Console.WriteLine("Did not send data update event. dataScope is an empty list");
return;
}
}
else
{
if (dataScope != null)
Console.WriteLine(
"Did not send data update event. dataScope is not a string or list of strings"
);
return;
}

// a string representation of the data scope result to use when finding an existing message
// for the event
string dataScopeKey;
if (dataScopeResult is string sR)
dataScopeKey = sR;
else if (dataScopeResult is List<string> dataScopeListR)
dataScopeKey = string.Join(',', dataScopeListR);
else
{
Console.WriteLine(
$"dataScopeResult {dataScopeResult} was not string or list of strings. Unable to send data update event"
);
return;
}

var dataUpdateEventMessage = _updateEventsByScope.GetOrAdd(
scopeString,
(scope) => new MessageEventDataUpdated(_eventType, scope)
dataScopeKey,
(scope, result) => new MessageEventDataUpdated(_eventType, result),
dataScopeResult
);
PapiClient.SendEvent(dataUpdateEventMessage);
}
Expand Down
16 changes: 13 additions & 3 deletions c-sharp/Projects/ParatextProjectStorageInterpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ internal class ParatextProjectStorageInterpreter : ProjectStorageInterpreter
public const string VerseUSFM = "VerseUSFM";
public const string ChapterUSX = "ChapterUSX";

// All data types related to Scripture editing. Changes to any portion of Scripture should send
// out updates to all these data types
public static readonly List<string> AllScriptureDataTypes = new List<string>
{
BookUSFM,
ChapterUSFM,
VerseUSFM,
ChapterUSX
};

private readonly LocalProjects _projects;
#endregion

Expand Down Expand Up @@ -152,8 +162,8 @@ public override ResponseToRequest SetProjectData(ProjectDataScope scope, string
);
}
);
// The value of returned string is case sensitive and cannot change unless data provider subscriptions change
return ResponseToRequest.Succeeded(ChapterUSFM);
// The value of returned strings are case sensitive and cannot change unless data provider subscriptions change
return ResponseToRequest.Succeeded(AllScriptureDataTypes);
case ChapterUSX:
if (!string.IsNullOrEmpty(error))
return ResponseToRequest.Failed(error);
Expand Down Expand Up @@ -284,7 +294,7 @@ out string usfm
return ResponseToRequest.Failed(e.ToString());
}

return ResponseToRequest.Succeeded(ChapterUSX);
return ResponseToRequest.Succeeded(AllScriptureDataTypes);
}

private static XmlDocument ConvertUsfmToUsx(ScrText scrText, string usfm, int bookNum)
Expand Down

0 comments on commit efd9c11

Please sign in to comment.