Skip to content

Commit

Permalink
Changed instance update to reflect various json merge needs (#359)
Browse files Browse the repository at this point in the history
* Changed instance update to reflect various json merge needs. Cases:
- Process: Insert complete json
- Substatus: Insert complete json
- Status: Merge propertis based on updateProperties in repo api
- CompleteConfirmations: Merge properties
- Datavalues: Merge properties
- PresentationTexts: Merge properties
- Other top level properties (lastchanged and lastchangedby): Merge properties
- "Complications": Process and Substatus might be combined, and the different combinations must be treated separately

* Changed property of appsettings.json to "copy allways"

---------

Co-authored-by: Henning Normann <h.normann@accenture.com>
  • Loading branch information
HenningNormann and HenningNormann authored Apr 8, 2024
1 parent c42e19b commit 83f7979
Show file tree
Hide file tree
Showing 6 changed files with 279 additions and 56 deletions.
3 changes: 0 additions & 3 deletions src/Storage/Controllers/InstancesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -610,10 +610,7 @@ public async Task<ActionResult<Instance>> UpdateSubstatus(
try
{
List<string> updateProperties = [
nameof(instance.Status),
nameof(instance.Status.Substatus),
nameof(instance.Status.Substatus.Description),
nameof(instance.Status.Substatus.Label),
nameof(instance.LastChanged),
nameof(instance.LastChangedBy)
];
Expand Down
15 changes: 0 additions & 15 deletions src/Storage/Controllers/ProcessController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,21 +118,6 @@ public async Task<ActionResult<Instance>> PutProcess(
// Archiving instance if process was ended
List<string> updateProperties = [
nameof(existingInstance.Process),
nameof(existingInstance.Process.CurrentTask),
nameof(existingInstance.Process.CurrentTask.AltinnTaskType),
nameof(existingInstance.Process.CurrentTask.ElementId),
nameof(existingInstance.Process.CurrentTask.Ended),
nameof(existingInstance.Process.CurrentTask.Flow),
nameof(existingInstance.Process.CurrentTask.FlowType),
nameof(existingInstance.Process.CurrentTask.Name),
nameof(existingInstance.Process.CurrentTask.Started),
nameof(existingInstance.Process.CurrentTask.Validated),
nameof(existingInstance.Process.CurrentTask.Validated.Timestamp),
nameof(existingInstance.Process.CurrentTask.Validated.CanCompleteTask),
nameof(existingInstance.Process.Ended),
nameof(existingInstance.Process.EndEvent),
nameof(existingInstance.Process.Started),
nameof(existingInstance.Process.StartEvent),
nameof(existingInstance.LastChanged),
nameof(existingInstance.LastChangedBy)
];
Expand Down
135 changes: 135 additions & 0 deletions src/Storage/Migration/v0.06/01-functions-and-procedures.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
CREATE OR REPLACE FUNCTION storage.updateinstance_v2(
_alternateid UUID,
_toplevelsimpleprops JSONB,
_datavalues JSONB,
_completeconfirmations JSONB,
_presentationtexts JSONB,
_status JSONB,
_substatus JSONB,
_process JSONB,
_lastchanged TIMESTAMPTZ,
_taskid TEXT)
RETURNS TABLE (updatedInstance JSONB)
LANGUAGE 'plpgsql'
AS $BODY$
BEGIN
IF _datavalues IS NOT NULL THEN
RETURN QUERY
UPDATE storage.instances SET
instance = instance || _toplevelsimpleprops ||
jsonb_strip_nulls(
jsonb_set(
'{"DataValues":""}',
'{DataValues}',
CASE WHEN instance -> 'DataValues' IS NOT NULL THEN
instance -> 'DataValues' || _datavalues
ELSE
_datavalues
END
)
),
lastchanged = _lastchanged
WHERE _alternateid = alternateid
RETURNING instance;
ELSIF _presentationtexts IS NOT NULL THEN
RETURN QUERY
UPDATE storage.instances SET
instance = instance || _toplevelsimpleprops ||
jsonb_strip_nulls(
jsonb_set(
'{"PresentationTexts":""}',
'{PresentationTexts}',
CASE WHEN instance -> 'PresentationTexts' IS NOT NULL THEN
instance -> 'PresentationTexts' || _presentationtexts
ELSE
_presentationtexts
END
)
),
lastchanged = _lastchanged
WHERE _alternateid = alternateid
RETURNING instance;
ELSIF _completeconfirmations IS NOT NULL THEN
RETURN QUERY
UPDATE storage.instances SET
instance = instance || _toplevelsimpleprops ||
jsonb_set(
'{"CompleteConfirmations":""}',
'{CompleteConfirmations}',
CASE WHEN instance -> 'CompleteConfirmations' IS NOT NULL THEN
instance -> 'CompleteConfirmations' || _completeconfirmations
ELSE
_completeconfirmations
END
),
lastchanged = _lastchanged
WHERE _alternateid = alternateid
RETURNING instance;
ELSIF _status IS NOT NULL AND _process IS NULL THEN
RETURN QUERY
UPDATE storage.instances SET
instance = instance ||
jsonb_set(
instance || _toplevelsimpleprops,
'{Status}',
CASE WHEN instance -> 'Status' IS NOT NULL THEN
instance -> 'Status' || _status
ELSE
_status
END
),
lastchanged = _lastchanged
WHERE _alternateid = alternateid
RETURNING instance;
ELSIF _substatus IS NOT NULL THEN
RETURN QUERY
UPDATE storage.instances SET
instance = instance ||
jsonb_set(
instance || _toplevelsimpleprops,
'{Status, Substatus}',
jsonb_strip_nulls(_substatus)
),
lastchanged = _lastchanged
WHERE _alternateid = alternateid
RETURNING instance;
ELSIF _process IS NOT NULL AND _status IS NOT NULL THEN
RETURN QUERY
UPDATE storage.instances SET
instance = instance ||
jsonb_set(
instance || _toplevelsimpleprops,
'{Process}',
jsonb_strip_nulls(_process)
) ||
jsonb_set(
'{"Status":""}',
'{Status}',
CASE WHEN instance -> 'Status' IS NOT NULL THEN
instance -> 'Status' || _status
ELSE
_status
END
),
lastchanged = _lastchanged,
taskid = _taskid
WHERE _alternateid = alternateid
RETURNING instance;
ELSIF _process IS NOT NULL THEN
RETURN QUERY
UPDATE storage.instances SET
instance = instance ||
jsonb_set(
instance || _toplevelsimpleprops,
'{Process}',
jsonb_strip_nulls(_process)
),
lastchanged = _lastchanged,
taskid = _taskid
WHERE _alternateid = alternateid
RETURNING instance;
ELSE
RAISE EXCEPTION 'Unexpected parameters to update instance';
END IF;
END;
$BODY$;
18 changes: 11 additions & 7 deletions src/Storage/Repository/PgInstanceRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class PgInstanceRepository: IInstanceRepository
private const string _readSqlFilteredInitial = "select * from storage.readinstancefromquery_v2 (";
private readonly string _deleteSql = "select * from storage.deleteinstance ($1)";
private readonly string _insertSql = "call storage.insertinstance ($1, $2, $3, $4, $5, $6, $7, $8)";
private readonly string _updateSql = "select * from storage.updateinstance ($1, $2, $3, $4, $5, $6)";
private readonly string _updateSql = "select * from storage.updateinstance_v2 (@_alternateid, @_toplevelsimpleprops, @_datavalues, @_completeconfirmations, @_presentationtexts, @_status, @_substatus, @_process, @_lastchanged, @_taskid)";
private readonly string _readSql = "select * from storage.readinstance ($1)";
private readonly string _readSqlFiltered = _readSqlFilteredInitial;
private readonly string _readDeletedSql = "select * from storage.readdeletedinstances ()";
Expand Down Expand Up @@ -377,12 +377,16 @@ public async Task<Instance> Update(Instance instance, List<string> updatePropert
instance.Data = null;
await using NpgsqlCommand pgcom = _dataSource.CreateCommand(_updateSql);
using TelemetryTracker tracker = new(_telemetryClient, pgcom);
pgcom.Parameters.AddWithValue(NpgsqlDbType.Uuid, new Guid(instance.Id));
pgcom.Parameters.AddWithValue(NpgsqlDbType.Jsonb, CustomSerializer.Serialize(instance, updateProperties));
pgcom.Parameters.AddWithValue(NpgsqlDbType.Jsonb, updateProperties.Contains(nameof(instance.DataValues)) ? instance.DataValues : DBNull.Value);
pgcom.Parameters.AddWithValue(NpgsqlDbType.Jsonb, updateProperties.Contains(nameof(instance.CompleteConfirmations)) ? instance.CompleteConfirmations : DBNull.Value);
pgcom.Parameters.AddWithValue(NpgsqlDbType.TimestampTz, instance.LastChanged ?? DateTime.UtcNow);
pgcom.Parameters.AddWithValue(NpgsqlDbType.Text, instance.Process?.CurrentTask?.ElementId ?? (object)DBNull.Value);
pgcom.Parameters.AddWithValue("_alternateid", NpgsqlDbType.Uuid, new Guid(instance.Id));
pgcom.Parameters.AddWithValue("_toplevelsimpleprops", NpgsqlDbType.Jsonb, CustomSerializer.Serialize(instance, updateProperties));
pgcom.Parameters.AddWithValue("_datavalues", NpgsqlDbType.Jsonb, updateProperties.Contains(nameof(instance.DataValues)) ? instance.DataValues : DBNull.Value);
pgcom.Parameters.AddWithValue("_completeconfirmations", NpgsqlDbType.Jsonb, updateProperties.Contains(nameof(instance.CompleteConfirmations)) ? instance.CompleteConfirmations : DBNull.Value);
pgcom.Parameters.AddWithValue("_presentationtexts", NpgsqlDbType.Jsonb, updateProperties.Contains(nameof(instance.PresentationTexts)) ? instance.PresentationTexts : DBNull.Value);
pgcom.Parameters.AddWithValue("_status", NpgsqlDbType.Jsonb, updateProperties.Contains(nameof(instance.Status)) ? CustomSerializer.Serialize(instance.Status, updateProperties) : DBNull.Value);
pgcom.Parameters.AddWithValue("_substatus", NpgsqlDbType.Jsonb, updateProperties.Contains(nameof(instance.Status.Substatus)) ? instance.Status.Substatus : DBNull.Value);
pgcom.Parameters.AddWithValue("_process", NpgsqlDbType.Jsonb, updateProperties.Contains(nameof(instance.Process)) ? instance.Process : DBNull.Value);
pgcom.Parameters.AddWithValue("_lastchanged", NpgsqlDbType.TimestampTz, instance.LastChanged ?? DateTime.UtcNow);
pgcom.Parameters.AddWithValue("_taskid", NpgsqlDbType.Text, instance.Process?.CurrentTask?.ElementId ?? (object)DBNull.Value);

await using NpgsqlDataReader reader = await pgcom.ExecuteReaderAsync();
if (await reader.ReadAsync())
Expand Down
6 changes: 6 additions & 0 deletions test/UnitTest/Altinn.Platform.Storage.UnitTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,10 @@
<_ContentIncludedByDefault Remove="data\roles\user_5\party_1337\roles.json" />
</ItemGroup>

<ItemGroup>
<Content Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>

</Project>
Loading

0 comments on commit 83f7979

Please sign in to comment.