Merge lp:~unity-api-team/unity-scopes-api/leverage-net-cpp-streaming-api into lp:unity-scopes-api/devel
- leverage-net-cpp-streaming-api
- Merge into devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Marcus Tomlinson | ||||
Approved revision: | 585 | ||||
Merged at revision: | 589 | ||||
Proposed branch: | lp:~unity-api-team/unity-scopes-api/leverage-net-cpp-streaming-api | ||||
Merge into: | lp:unity-scopes-api/devel | ||||
Diff against target: |
234 lines (+72/-41) 6 files modified
CMakeLists.txt (+1/-1) debian/control (+1/-1) include/unity/scopes/internal/smartscopes/HttpClientNetCpp.h (+2/-2) include/unity/scopes/internal/smartscopes/SmartScopesClient.h (+4/-2) src/scopes/internal/smartscopes/HttpClientNetCpp.cpp (+11/-11) src/scopes/internal/smartscopes/SmartScopesClient.cpp (+53/-24) |
||||
To merge this branch: | bzr merge lp:~unity-api-team/unity-scopes-api/leverage-net-cpp-streaming-api | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Michi Henning (community) | Approve | ||
Thomas Voß (community) | Approve | ||
Review via email: mp+256281@code.launchpad.net |
Commit message
Leverage the streaming API introduced in net-cpp 1.2.0.
Description of the change
Marcus Tomlinson (marcustomlinson) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:578
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Marcus Tomlinson (marcustomlinson) wrote : | # |
Need to wait for net-cpp to land before we can go ahead with this one.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:579
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Marcus Tomlinson (marcustomlinson) wrote : | # |
Re-approving as net-cpp has now landed
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:580
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:581
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:581
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:582
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:584
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:585
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Marcus Tomlinson (marcustomlinson) wrote : | # |
Oh gosh, benchmark test failure... Here goes another 2 hours of build time...
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-05-15 06:05:48 +0000 |
3 | +++ CMakeLists.txt 2015-05-18 06:26:24 +0000 |
4 | @@ -70,7 +70,7 @@ |
5 | pkg_check_modules(LIBACCOUNTS libaccounts-glib REQUIRED) |
6 | pkg_check_modules(LIBSIGNON libsignon-glib REQUIRED) |
7 | pkg_check_modules(ZMQLIB libzmq REQUIRED) |
8 | -pkg_check_modules(NET_CPP net-cpp REQUIRED) |
9 | +pkg_check_modules(NET_CPP net-cpp>=1.2.0 REQUIRED) |
10 | |
11 | find_library(ZMQPPLIB zmqpp) |
12 | if(NOT ZMQPPLIB) |
13 | |
14 | === modified file 'debian/control' |
15 | --- debian/control 2015-05-15 00:25:07 +0000 |
16 | +++ debian/control 2015-05-18 06:26:24 +0000 |
17 | @@ -20,7 +20,7 @@ |
18 | libdbustest1-dev, |
19 | libjsoncpp-dev, |
20 | liblttng-ust-dev, |
21 | - libnet-cpp-dev, |
22 | + libnet-cpp-dev (>= 1.2.0), |
23 | libprocess-cpp-dev (>= 1.0.1), |
24 | libsignon-glib-dev, |
25 | libunity-api-dev (>= 7.80.7~), |
26 | |
27 | === modified file 'include/unity/scopes/internal/smartscopes/HttpClientNetCpp.h' |
28 | --- include/unity/scopes/internal/smartscopes/HttpClientNetCpp.h 2015-01-16 06:13:57 +0000 |
29 | +++ include/unity/scopes/internal/smartscopes/HttpClientNetCpp.h 2015-05-18 06:26:24 +0000 |
30 | @@ -30,7 +30,7 @@ |
31 | { |
32 | namespace http |
33 | { |
34 | -class Client; |
35 | +class StreamingClient; |
36 | } |
37 | } |
38 | } |
39 | @@ -63,7 +63,7 @@ |
40 | void cancel_get(unsigned int session_id) override; |
41 | |
42 | unsigned int no_reply_timeout; |
43 | - std::shared_ptr<core::net::http::Client> client; |
44 | + std::shared_ptr<core::net::http::StreamingClient> client; |
45 | std::thread worker; |
46 | }; |
47 | |
48 | |
49 | === modified file 'include/unity/scopes/internal/smartscopes/SmartScopesClient.h' |
50 | --- include/unity/scopes/internal/smartscopes/SmartScopesClient.h 2015-01-28 09:03:59 +0000 |
51 | +++ include/unity/scopes/internal/smartscopes/SmartScopesClient.h 2015-05-18 06:26:24 +0000 |
52 | @@ -215,8 +215,10 @@ |
53 | std::shared_ptr<DepartmentInfo> parse_departments(JsonNodeInterface::SPtr node); |
54 | Filters parse_filters(JsonNodeInterface::SPtr node); |
55 | FilterState parse_filter_state(JsonNodeInterface::SPtr node); |
56 | - void parse_line(std::string const& json, SearchReplyHandler const& handler); |
57 | - void parse_line(std::string const& json, PreviewReplyHandler const& handler); |
58 | + |
59 | + std::string handle_chunk(const std::string& chunk, std::function<void(const std::string&)> line_handler); |
60 | + void handle_line(std::string const& json, SearchReplyHandler const& handler); |
61 | + void handle_line(std::string const& json, PreviewReplyHandler const& handler); |
62 | |
63 | std::vector<std::string> extract_json_stream(std::string const& json_stream); |
64 | |
65 | |
66 | === modified file 'src/scopes/internal/smartscopes/HttpClientNetCpp.cpp' |
67 | --- src/scopes/internal/smartscopes/HttpClientNetCpp.cpp 2015-01-19 09:15:06 +0000 |
68 | +++ src/scopes/internal/smartscopes/HttpClientNetCpp.cpp 2015-05-18 06:26:24 +0000 |
69 | @@ -20,8 +20,8 @@ |
70 | |
71 | #include <unity/UnityExceptions.h> |
72 | |
73 | -#include <core/net/http/client.h> |
74 | -#include <core/net/http/request.h> |
75 | +#include <core/net/http/streaming_client.h> |
76 | +#include <core/net/http/streaming_request.h> |
77 | #include <core/net/http/response.h> |
78 | #include <core/net/http/status.h> |
79 | |
80 | @@ -102,7 +102,7 @@ |
81 | |
82 | HttpClientNetCpp::HttpClientNetCpp(unsigned int no_reply_timeout) |
83 | : no_reply_timeout{no_reply_timeout}, |
84 | - client{http::make_client()}, |
85 | + client{http::make_streaming_client()}, |
86 | worker([this]() { client->run(); }) |
87 | { |
88 | } |
89 | @@ -129,7 +129,7 @@ |
90 | } |
91 | http_config.header = http_header; |
92 | |
93 | - auto request = client->get(http_config); |
94 | + auto request = client->streaming_get(http_config); |
95 | request->set_timeout(std::chrono::milliseconds{no_reply_timeout}); |
96 | |
97 | auto promise = std::make_shared<std::promise<void>>(); |
98 | @@ -157,12 +157,8 @@ |
99 | } |
100 | else |
101 | { |
102 | - std::istringstream in(response.body); |
103 | - std::string line; |
104 | - while (std::getline(in, line)) |
105 | - { |
106 | - line_data(line); |
107 | - } |
108 | + // call line_data with empty string to signal end of chunked data |
109 | + line_data(""); |
110 | promise->set_value(); |
111 | } |
112 | }) |
113 | @@ -170,7 +166,11 @@ |
114 | { |
115 | unity::ResourceException re(e.what()); |
116 | promise->set_exception(std::make_exception_ptr(re)); |
117 | - })); |
118 | + }), |
119 | + [line_data](const std::string& const_data) |
120 | + { |
121 | + line_data(const_data); |
122 | + }); |
123 | |
124 | return std::make_shared<HttpResponseHandle>( |
125 | shared_from_this(), |
126 | |
127 | === modified file 'src/scopes/internal/smartscopes/SmartScopesClient.cpp' |
128 | --- src/scopes/internal/smartscopes/SmartScopesClient.cpp 2015-04-10 03:55:25 +0000 |
129 | +++ src/scopes/internal/smartscopes/SmartScopesClient.cpp 2015-05-18 06:26:24 +0000 |
130 | @@ -472,18 +472,17 @@ |
131 | headers.push_back(std::make_pair("User-Agent", user_agent_hdr)); |
132 | } |
133 | |
134 | - auto reponse_mutex = std::make_shared<std::mutex>(); |
135 | - query_results_[search_id] = http_client_->get(search_uri.str(), [this, handler, reponse_mutex](std::string const& line_data) |
136 | + auto tmp_data = std::make_shared<std::string>(); |
137 | + query_results_[search_id] = http_client_->get(search_uri.str(), [this, tmp_data, handler](std::string const& chunk) |
138 | { |
139 | - std::lock_guard<std::mutex> lock(*reponse_mutex); |
140 | - try |
141 | - { |
142 | - parse_line(line_data, handler); |
143 | - } |
144 | - catch (std::exception const &e) |
145 | - { |
146 | - BOOST_LOG_SEV(logger_, Logger::Error) << "SmartScopesClient.search(): Failed to parse: " << e.what(); |
147 | - } |
148 | + // prepend any leftover data from the previous handle_chunk call |
149 | + std::string data = *tmp_data + (chunk.empty() ? "\n" : chunk); |
150 | + |
151 | + // store the leftover data from the handle_chunk call into tmp_data |
152 | + *tmp_data = handle_chunk(data, [this, handler](const std::string& line) |
153 | + { |
154 | + handle_line(line, handler); |
155 | + }); |
156 | }, headers); |
157 | |
158 | return SearchHandle::UPtr(new SearchHandle(search_id, shared_from_this())); |
159 | @@ -540,24 +539,54 @@ |
160 | |
161 | BOOST_LOG_SEV(logger_, Logger::Info) << "SmartScopesClient.preview(): GET " << preview_uri.str(); |
162 | |
163 | - auto reponse_mutex = std::make_shared<std::mutex>(); |
164 | - query_results_[preview_id] = http_client_->get(preview_uri.str(), [this, handler, reponse_mutex](std::string const& line_data) |
165 | + auto tmp_data = std::make_shared<std::string>(); |
166 | + query_results_[preview_id] = http_client_->get(preview_uri.str(), [this, tmp_data, handler](std::string const& chunk) |
167 | { |
168 | - std::lock_guard<std::mutex> lock(*reponse_mutex); |
169 | - try |
170 | - { |
171 | - parse_line(line_data, handler); |
172 | - } |
173 | - catch (std::exception const &e) |
174 | - { |
175 | - BOOST_LOG_SEV(logger_, Logger::Error) << "SmartScopesClient.preview(): Failed to parse: " << e.what(); |
176 | - } |
177 | + // prepend any leftover data from the previous handle_chunk call |
178 | + std::string data = *tmp_data + (chunk.empty() ? "\n" : chunk); |
179 | + |
180 | + // store the leftover data from the handle_chunk call into tmp_data |
181 | + *tmp_data = handle_chunk(data, [this, handler](const std::string& line) |
182 | + { |
183 | + handle_line(line, handler); |
184 | + }); |
185 | }, headers); |
186 | |
187 | return PreviewHandle::UPtr(new PreviewHandle(preview_id, shared_from_this())); |
188 | } |
189 | |
190 | -void SmartScopesClient::parse_line(std::string const& json, PreviewReplyHandler const& handler) |
191 | +std::string SmartScopesClient::handle_chunk(const std::string& chunk, std::function<void(const std::string&)> line_handler) |
192 | +{ |
193 | + // According to the docs, we expect: |
194 | + // The response will have Content-Type |
195 | + // application/json, it will be a chunked response, in practice a series of |
196 | + // “\r\n” delimited lines, each containing one JSON object, with the |
197 | + // possible forms, matching what currently can be pushed into a reply in the |
198 | + // new scopes API |
199 | + static constexpr const char separator{'\n'}; |
200 | + |
201 | + // read data line-by-line calling line_handler() for each |
202 | + auto newline_pos = 0; |
203 | + auto endline_pos = chunk.find(separator); |
204 | + while (endline_pos != std::string::npos) |
205 | + { |
206 | + try |
207 | + { |
208 | + line_handler(chunk.substr(newline_pos, endline_pos - newline_pos)); |
209 | + } |
210 | + catch (std::exception const &e) |
211 | + { |
212 | + BOOST_LOG_SEV(logger_, Logger::Error) << "SmartScopesClient.handle_chunk(): Failed to parse line: " << e.what(); |
213 | + } |
214 | + newline_pos = endline_pos + 1; |
215 | + endline_pos = chunk.find(separator, newline_pos); |
216 | + } |
217 | + |
218 | + // return the leftover data |
219 | + return chunk.substr(newline_pos, chunk.size() - newline_pos); |
220 | +} |
221 | + |
222 | +void SmartScopesClient::handle_line(std::string const& json, PreviewReplyHandler const& handler) |
223 | { |
224 | JsonNodeInterface::SPtr root_node; |
225 | JsonNodeInterface::SPtr child_node; |
226 | @@ -605,7 +634,7 @@ |
227 | } |
228 | } |
229 | |
230 | -void SmartScopesClient::parse_line(std::string const& json, SearchReplyHandler const& handler) |
231 | +void SmartScopesClient::handle_line(std::string const& json, SearchReplyHandler const& handler) |
232 | { |
233 | JsonNodeInterface::SPtr root_node; |
234 | JsonNodeInterface::SPtr child_node; |
This is a copy of lp:~thomas-voss/unity-scopes-api/leverage-net-cpp-streaming-api, with buffering of partial json chucks added to SmartScopesClient.