Line data Source code
1 : #ifndef SOCIAL_NETWORK_MICROSERVICES_TEXTHANDLER_H
2 : #define SOCIAL_NETWORK_MICROSERVICES_TEXTHANDLER_H
3 :
4 : #include <future>
5 : #include <iostream>
6 : #include <regex>
7 : #include <string>
8 :
9 : #include "../../gen-cpp/TextService.h"
10 : #include "../../gen-cpp/UrlShortenService.h"
11 : #include "../../gen-cpp/UserMentionService.h"
12 : #include "../ClientPool.h"
13 : #include "../ThriftClient.h"
14 : #include "../logger.h"
15 : #include "../tracing.h"
16 :
17 : namespace social_network {
18 :
19 : class TextHandler : public TextServiceIf {
20 : public:
21 : TextHandler(ClientPool<ThriftClient<UrlShortenServiceClient>> *,
22 : ClientPool<ThriftClient<UserMentionServiceClient>> *);
23 0 : ~TextHandler() override = default;
24 :
25 : void ComposeText(TextServiceReturn &_return, int64_t, const std::string &,
26 : const std::map<std::string, std::string> &) override;
27 :
28 : private:
29 : ClientPool<ThriftClient<UrlShortenServiceClient>> *_url_client_pool;
30 : ClientPool<ThriftClient<UserMentionServiceClient>> *_user_mention_client_pool;
31 : };
32 :
33 1 : TextHandler::TextHandler(
34 : ClientPool<ThriftClient<UrlShortenServiceClient>> *url_client_pool,
35 : ClientPool<ThriftClient<UserMentionServiceClient>>
36 1 : *user_mention_client_pool) {
37 1 : _url_client_pool = url_client_pool;
38 1 : _user_mention_client_pool = user_mention_client_pool;
39 1 : }
40 :
41 200 : void TextHandler::ComposeText(
42 : TextServiceReturn &_return, int64_t req_id, const std::string &text,
43 : const std::map<std::string, std::string> &carrier) {
44 : // 新增:记录收到的 ComposeText 请求
45 400 : LOG(info) << "Received ComposeText request [req_id=" << req_id << ", text length=" << text.length() << "]";
46 :
47 : // Initialize a span
48 400 : TextMapReader reader(carrier);
49 400 : std::map<std::string, std::string> writer_text_map;
50 400 : TextMapWriter writer(writer_text_map);
51 400 : auto parent_span = opentracing::Tracer::Global()->Extract(reader);
52 400 : auto span = opentracing::Tracer::Global()->StartSpan(
53 800 : "compose_text_server", {opentracing::ChildOf(parent_span->get())});
54 200 : opentracing::Tracer::Global()->Inject(span->context(), writer);
55 :
56 400 : std::vector<std::string> mention_usernames;
57 400 : std::smatch m;
58 400 : std::regex e("@[a-zA-Z0-9-_]+");
59 400 : auto s = text;
60 200 : while (std::regex_search(s, m, e)) {
61 0 : auto user_mention = m.str();
62 0 : user_mention = user_mention.substr(1, user_mention.length());
63 0 : mention_usernames.emplace_back(user_mention);
64 0 : s = m.suffix().str();
65 : }
66 :
67 400 : std::vector<std::string> urls;
68 200 : e = "(http://|https://)([a-zA-Z0-9_!~*'().&=+$%-]+)";
69 200 : s = text;
70 200 : while (std::regex_search(s, m, e)) {
71 0 : auto url = m.str();
72 0 : urls.emplace_back(url);
73 0 : s = m.suffix().str();
74 : }
75 :
76 : // 新增:记录提取到的 @用户 和 URL 数量
77 400 : LOG(info) << "Extracted mentions and urls [req_id=" << req_id << ", mention count=" << mention_usernames.size() << ", url count=" << urls.size() << "]";
78 :
79 200 : auto shortened_urls_future = std::async(std::launch::async, [&]() {
80 400 : auto url_span = opentracing::Tracer::Global()->StartSpan(
81 800 : "compose_urls_client", {opentracing::ChildOf(&span->context())});
82 :
83 400 : std::map<std::string, std::string> url_writer_text_map;
84 400 : TextMapWriter url_writer(url_writer_text_map);
85 200 : opentracing::Tracer::Global()->Inject(url_span->context(), url_writer);
86 :
87 400 : auto url_client_wrapper = _url_client_pool->Pop();
88 200 : if (!url_client_wrapper) {
89 0 : ServiceException se;
90 0 : se.errorCode = ErrorCode::SE_THRIFT_CONN_ERROR;
91 0 : se.message = "Failed to connect to url-shorten-service";
92 0 : throw se;
93 : }
94 200 : std::vector<Url> _return_urls;
95 200 : auto url_client = url_client_wrapper->GetClient();
96 : try {
97 600 : url_client->ComposeUrls(_return_urls, req_id, urls, url_writer_text_map);
98 0 : } catch (...) {
99 0 : LOG(error) << "Failed to upload urls to url-shorten-service";
100 0 : _url_client_pool->Remove(url_client_wrapper);
101 0 : throw;
102 : }
103 200 : _url_client_pool->Keepalive(url_client_wrapper);
104 : // 新增:成功调用 url-shortener 服务日志
105 800 : LOG(info) << "ComposeUrls to url-shorten-service succeeded [req_id=" << req_id << ", url count=" << urls.size() << "]";
106 400 : return _return_urls;
107 400 : });
108 :
109 200 : auto user_mention_future = std::async(std::launch::async, [&]() {
110 400 : auto user_mention_span = opentracing::Tracer::Global()->StartSpan(
111 : "compose_user_mentions_client",
112 800 : {opentracing::ChildOf(&span->context())});
113 :
114 400 : std::map<std::string, std::string> user_mention_writer_text_map;
115 400 : TextMapWriter user_mention_writer(user_mention_writer_text_map);
116 600 : opentracing::Tracer::Global()->Inject(user_mention_span->context(),
117 400 : user_mention_writer);
118 :
119 400 : auto user_mention_client_wrapper = _user_mention_client_pool->Pop();
120 200 : if (!user_mention_client_wrapper) {
121 0 : ServiceException se;
122 0 : se.errorCode = ErrorCode::SE_THRIFT_CONN_ERROR;
123 0 : se.message = "Failed to connect to user-mention-service";
124 0 : throw se;
125 : }
126 200 : std::vector<UserMention> _return_user_mentions;
127 200 : auto user_mention_client = user_mention_client_wrapper->GetClient();
128 : try {
129 400 : user_mention_client->ComposeUserMentions(_return_user_mentions, req_id,
130 400 : mention_usernames,
131 400 : user_mention_writer_text_map);
132 0 : } catch (...) {
133 0 : LOG(error) << "Failed to upload user_mentions to user-mention-service";
134 0 : _user_mention_client_pool->Remove(user_mention_client_wrapper);
135 0 : throw;
136 : }
137 :
138 200 : _user_mention_client_pool->Keepalive(user_mention_client_wrapper);
139 : // 新增:成功调用 user-mention 服务日志
140 800 : LOG(info) << "ComposeUserMentions to user-mention-service succeeded [req_id=" << req_id << ", mention count=" << mention_usernames.size() << "]";
141 400 : return _return_user_mentions;
142 400 : });
143 :
144 400 : std::vector<Url> target_urls;
145 : try {
146 200 : target_urls = shortened_urls_future.get();
147 0 : } catch (...) {
148 0 : LOG(error) << "Failed to get shortened urls from url-shorten-service";
149 0 : throw;
150 : }
151 :
152 400 : std::vector<UserMention> user_mentions;
153 : try {
154 200 : user_mentions = user_mention_future.get();
155 0 : } catch (...) {
156 0 : LOG(error) << "Failed to upload user mentions to user-mention-service";
157 0 : throw;
158 : }
159 :
160 400 : std::string updated_text;
161 200 : if (!urls.empty()) {
162 0 : s = text;
163 0 : int idx = 0;
164 0 : while (std::regex_search(s, m, e)) {
165 0 : auto url = m.str();
166 0 : urls.emplace_back(url);
167 0 : updated_text += m.prefix().str() + target_urls[idx].shortened_url;
168 0 : s = m.suffix().str();
169 0 : idx++;
170 : }
171 : } else {
172 200 : updated_text = text;
173 : }
174 :
175 200 : _return.user_mentions = user_mentions;
176 200 : _return.text = updated_text;
177 200 : _return.urls = target_urls;
178 :
179 : // 新增:方法结束日志
180 400 : LOG(info) << "ComposeText completed [req_id=" << req_id << ", user_mentions count=" << user_mentions.size() << ", urls count=" << target_urls.size() << "]";
181 :
182 200 : span->Finish();
183 200 : }
184 :
185 : } // namespace social_network
186 :
187 : #endif // SOCIAL_NETWORK_MICROSERVICES_TEXTHANDLER_H
|