comparison OrthancServer/Sources/OrthancRestApi/OrthancRestChanges.cpp @ 5757:5463c3ae3235 large-queries

refactored extended /changes
author Alain Mazy <am@orthanc.team>
date Thu, 05 Sep 2024 18:21:56 +0200
parents 3765085693e5
children ca06dde85358
comparison
equal deleted inserted replaced
5663:3765085693e5 5757:5463c3ae3235
27 #include "../ServerContext.h" 27 #include "../ServerContext.h"
28 28
29 namespace Orthanc 29 namespace Orthanc
30 { 30 {
31 // Changes API -------------------------------------------------------------- 31 // Changes API --------------------------------------------------------------
32 static const unsigned int DEFAULT_LIMIT = 100;
33 static const int64_t DEFAULT_TO = -1;
32 34
33 static void GetSinceToAndLimit(int64_t& since, 35 static void GetSinceToAndLimit(int64_t& since,
34 int64_t& to, 36 int64_t& to,
35 unsigned int& limit, 37 unsigned int& limit,
36 bool& last, 38 bool& last,
37 const RestApiGetCall& call) 39 const RestApiGetCall& call)
38 { 40 {
39 static const unsigned int DEFAULT_LIMIT = 100;
40 static const int64_t DEFAULT_TO = -1;
41
42 if (call.HasArgument("last")) 41 if (call.HasArgument("last"))
43 { 42 {
44 last = true; 43 last = true;
45 return; 44 return;
46 } 45 }
68 { 67 {
69 call.GetDocumentation() 68 call.GetDocumentation()
70 .SetTag("Tracking changes") 69 .SetTag("Tracking changes")
71 .SetSummary("List changes") 70 .SetSummary("List changes")
72 .SetDescription("Whenever Orthanc receives a new DICOM instance, this event is recorded in the so-called _Changes Log_. This enables remote scripts to react to the arrival of new DICOM resources. A typical application is auto-routing, where an external script waits for a new DICOM instance to arrive into Orthanc, then forward this instance to another modality.") 71 .SetDescription("Whenever Orthanc receives a new DICOM instance, this event is recorded in the so-called _Changes Log_. This enables remote scripts to react to the arrival of new DICOM resources. A typical application is auto-routing, where an external script waits for a new DICOM instance to arrive into Orthanc, then forward this instance to another modality.")
72 .SetHttpGetArgument("last", RestApiCallDocumentation::Type_Number, "Request only the last change id (this argument must be used alone)", false)
73 .SetHttpGetArgument("limit", RestApiCallDocumentation::Type_Number, "Limit the number of results", false) 73 .SetHttpGetArgument("limit", RestApiCallDocumentation::Type_Number, "Limit the number of results", false)
74 .SetHttpGetArgument("since", RestApiCallDocumentation::Type_Number, "Show only the resources since the provided index", false) 74 .SetHttpGetArgument("since", RestApiCallDocumentation::Type_Number, "Show only the resources since the provided index excluded", false)
75 .SetHttpGetArgument("to", RestApiCallDocumentation::Type_Number, "Show only the resources till the provided index included (only available if your DB backend supports ExtendedChanges)", false)
76 .SetHttpGetArgument("type", RestApiCallDocumentation::Type_String, "Show only the changes of the provided type (only available if your DB backend supports ExtendedChanges)", false)
75 .AddAnswerType(MimeType_Json, "The list of changes") 77 .AddAnswerType(MimeType_Json, "The list of changes")
76 .SetAnswerField("Changes", RestApiCallDocumentation::Type_JsonListOfObjects, "The individual changes") 78 .SetAnswerField("Changes", RestApiCallDocumentation::Type_JsonListOfObjects, "The individual changes")
77 .SetAnswerField("Done", RestApiCallDocumentation::Type_Boolean, 79 .SetAnswerField("Done", RestApiCallDocumentation::Type_Boolean,
78 "Whether the last reported change is the last of the full history") 80 "Whether the last reported change is the last of the full history.")
79 .SetAnswerField("Last", RestApiCallDocumentation::Type_Number, 81 .SetAnswerField("Last", RestApiCallDocumentation::Type_Number,
80 "The index of the last reported change, can be used for the `since` argument in subsequent calls to this route") 82 "The index of the last reported change, can be used for the `since` argument in subsequent calls to this route")
81 .SetHttpGetSample("https://orthanc.uclouvain.be/demo/changes?since=0&limit=2", true); 83 .SetAnswerField("First", RestApiCallDocumentation::Type_Number,
82 return; 84 "The index of the first reported change, its value-1 can be used for the `to` argument in subsequent calls to this route when browsing the changes in reverse order")
83 }
84
85 ServerContext& context = OrthancRestApi::GetContext(call);
86
87 int64_t since;
88 int64_t toNotUsed;
89 unsigned int limit;
90 bool last;
91 GetSinceToAndLimit(since, toNotUsed, limit, last, call);
92
93 Json::Value result;
94 if (last)
95 {
96 context.GetIndex().GetLastChange(result);
97 }
98 else
99 {
100 context.GetIndex().GetChanges(result, since, limit);
101 }
102
103 call.GetOutput().AnswerJson(result);
104 }
105
106 static void GetChanges2(RestApiGetCall& call)
107 {
108 if (call.IsDocumentation())
109 {
110 call.GetDocumentation()
111 .SetTag("Tracking changes")
112 .SetSummary("List changes")
113 .SetDescription("Whenever Orthanc receives a new DICOM instance, this event is recorded in the so-called _Changes Log_. This enables remote scripts to react to the arrival of new DICOM resources. A typical application is auto-routing, where an external script waits for a new DICOM instance to arrive into Orthanc, then forward this instance to another modality.")
114 .SetHttpGetArgument("limit", RestApiCallDocumentation::Type_Number, "Limit the number of results", false)
115 .SetHttpGetArgument("since", RestApiCallDocumentation::Type_Number, "Show only the resources since the provided index", false)
116 .SetHttpGetArgument("to", RestApiCallDocumentation::Type_Number, "Show only the resources till the provided index", false)
117 .SetHttpGetArgument("type", RestApiCallDocumentation::Type_String, "Show only the changes of the provided type", false)
118 .AddAnswerType(MimeType_Json, "The list of changes")
119 .SetAnswerField("Changes", RestApiCallDocumentation::Type_JsonListOfObjects, "The individual changes")
120 .SetAnswerField("Done", RestApiCallDocumentation::Type_Boolean,
121 "Whether the last reported change is the last of the full history")
122 .SetAnswerField("Last", RestApiCallDocumentation::Type_Number,
123 "The index of the last reported change, can be used for the `since` argument in subsequent calls to this route")
124 .SetHttpGetSample("https://orthanc.uclouvain.be/demo/changes?since=0&limit=2", true); 85 .SetHttpGetSample("https://orthanc.uclouvain.be/demo/changes?since=0&limit=2", true);
125 return; 86 return;
126 } 87 }
127 88
128 ServerContext& context = OrthancRestApi::GetContext(call); 89 ServerContext& context = OrthancRestApi::GetContext(call);
143 Json::Value result; 104 Json::Value result;
144 if (last) 105 if (last)
145 { 106 {
146 context.GetIndex().GetLastChange(result); 107 context.GetIndex().GetLastChange(result);
147 } 108 }
109 else if (context.GetIndex().HasExtendedChanges())
110 {
111 context.GetIndex().GetChangesExtended(result, since, to, limit, filterType);
112 }
148 else 113 else
149 { 114 {
150 if (filterType != ChangeType_INTERNAL_All && !context.GetIndex().HasExtendedApiV1()) 115 if (filterType != ChangeType_INTERNAL_All)
151 { 116 {
152 throw OrthancException(ErrorCode_ParameterOutOfRange, "Trying to filter changes while the Database backend does not support it (requires ExtendedApiV1)"); 117 throw OrthancException(ErrorCode_ParameterOutOfRange, "CAPABILITIES: Trying to filter changes while the Database backend does not support it (requires a DB backend with support for ExtendedChanges)");
153 } 118 }
154 119
155 context.GetIndex().GetChanges2(result, since, to, limit, filterType); 120 if (to != DEFAULT_TO)
121 {
122 throw OrthancException(ErrorCode_ParameterOutOfRange, "CAPABILITIES: Trying to use the 'to' parameter in /changes while the Database backend does not support it (requires a DB backend with support for ExtendedChanges)");
123 }
124
125 context.GetIndex().GetChanges(result, since, limit);
156 } 126 }
157 127
158 call.GetOutput().AnswerJson(result); 128 call.GetOutput().AnswerJson(result);
159 } 129 }
160 130
237 { 207 {
238 Register("/changes", GetChanges); 208 Register("/changes", GetChanges);
239 Register("/changes", DeleteChanges); 209 Register("/changes", DeleteChanges);
240 Register("/exports", GetExports); 210 Register("/exports", GetExports);
241 Register("/exports", DeleteExports); 211 Register("/exports", DeleteExports);
242 if (context_.GetIndex().HasExtendedApiV1())
243 {
244 Register("/extended-api-v1/changes", GetChanges2);
245 }
246 } 212 }
247 } 213 }