LCOV - code coverage report
Current view: top level - src/UrlShortenService - UrlShortenHandler.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 26 91 28.6 %
Date: 2025-11-03 22:48:57 Functions: 2 7 28.6 %

          Line data    Source code
       1             : #ifndef SOCIAL_NETWORK_MICROSERVICES_SRC_URLSHORTENSERVICE_URLSHORTENHANDLER_H_
       2             : #define SOCIAL_NETWORK_MICROSERVICES_SRC_URLSHORTENSERVICE_URLSHORTENHANDLER_H_
       3             : 
       4             : #include <random>
       5             : #include <chrono>
       6             : #include <future>
       7             : 
       8             : #include <mongoc.h>
       9             : #include <libmemcached/memcached.h>
      10             : #include <libmemcached/util.h>
      11             : #include <bson/bson.h>
      12             : 
      13             : #include "../../gen-cpp/UrlShortenService.h"
      14             : #include "../../gen-cpp/social_network_types.h"
      15             : #include "../logger.h"
      16             : #include "../tracing.h"
      17             : 
      18             : #define HOSTNAME "http://short-url/"
      19             : 
      20             : namespace social_network {
      21             : 
      22             : class UrlShortenHandler : public UrlShortenServiceIf {
      23             :  public:
      24             :   UrlShortenHandler(memcached_pool_st *, mongoc_client_pool_t *, std::mutex *);
      25           0 :   ~UrlShortenHandler() override = default;
      26             : 
      27             :   void ComposeUrls(std::vector<Url> &, int64_t,
      28             :       const std::vector<std::string> &,
      29             :       const std::map<std::string, std::string> &) override;
      30             : 
      31             :   void GetExtendedUrls(std::vector<std::string> &, int64_t,
      32             :                        const std::vector<std::string> &,
      33             :                        const std::map<std::string, std::string> &) override ;
      34             : 
      35             :  private:
      36             :   memcached_pool_st *_memcached_client_pool;
      37             :   mongoc_client_pool_t *_mongodb_client_pool;
      38             :   static std::mt19937 _generator;
      39             :   std::uniform_int_distribution<int> _distribution;
      40             :   std::string _GenRandomStr(int length);
      41             :   std::mutex *_thread_lock;
      42             : };
      43             : 
      44           2 : std::mt19937 UrlShortenHandler::_generator = std::mt19937(std::chrono::duration_cast<std::chrono::milliseconds>(
      45           3 :           std::chrono::system_clock::now().time_since_epoch()).count() % 0xffffffff);
      46             : 
      47           1 : UrlShortenHandler::UrlShortenHandler(
      48             :     memcached_pool_st *memcached_client_pool,
      49             :     mongoc_client_pool_t *mongodb_client_pool,
      50           1 :     std::mutex *thread_lock) {
      51           1 :   _memcached_client_pool = memcached_client_pool;
      52           1 :   _mongodb_client_pool = mongodb_client_pool;
      53           1 :   _thread_lock = thread_lock;
      54           1 :   _distribution = std::uniform_int_distribution<int>(0, 61);
      55           1 : }
      56             : 
      57           0 : std::string UrlShortenHandler::_GenRandomStr(int length) {
      58             :   const char char_map[] = "abcdefghijklmnopqrstuvwxyzABCDEF"
      59           0 :                     "GHIJKLMNOPQRSTUVWXYZ0123456789";
      60           0 :   std::string return_str;
      61           0 :   _thread_lock->lock();
      62           0 :   for (int i = 0; i < length; ++i) {
      63           0 :     return_str.append(1, char_map[_distribution(_generator)]);
      64             :   }
      65           0 :   _thread_lock->unlock();
      66           0 :   return return_str;
      67             : }
      68         200 : void UrlShortenHandler::ComposeUrls(
      69             :     std::vector<Url> &_return,
      70             :     int64_t req_id,
      71             :     const std::vector<std::string> &urls,
      72             :     const std::map<std::string, std::string> &carrier) {
      73             : 
      74             :   // 新增:记录收到的 ComposeUrls 请求
      75         400 :   LOG(info) << "Received ComposeUrls request [req_id=" << req_id << ", url count=" << urls.size() << "]";
      76             : 
      77             :   // Initialize a span
      78         400 :   TextMapReader reader(carrier);
      79         400 :   std::map<std::string, std::string> writer_text_map;
      80         400 :   TextMapWriter writer(writer_text_map);
      81         400 :   auto parent_span = opentracing::Tracer::Global()->Extract(reader);
      82         400 :   auto span = opentracing::Tracer::Global()->StartSpan(
      83             :       "compose_urls_server",
      84         800 :       { opentracing::ChildOf(parent_span->get()) });
      85         200 :   opentracing::Tracer::Global()->Inject(span->context(), writer);
      86             : 
      87         400 :   std::vector<Url> target_urls;
      88         400 :   std::future<void> mongo_future;
      89             : 
      90         200 :   if (!urls.empty()) {
      91           0 :     for (auto &url : urls) {
      92           0 :       Url new_target_url;
      93           0 :       new_target_url.expanded_url = url;
      94           0 :       new_target_url.shortened_url = HOSTNAME +
      95           0 :           _GenRandomStr(10);
      96           0 :       target_urls.emplace_back(new_target_url);
      97             :     }
      98             :     // 新增:记录生成的短链数量
      99           0 :     LOG(info) << "Generated short urls [req_id=" << req_id << ", count=" << target_urls.size() << "]";
     100             : 
     101           0 :     mongo_future = std::async(
     102           0 :         std::launch::async, [&](){
     103           0 :           mongoc_client_t *mongodb_client = mongoc_client_pool_pop(
     104           0 :               _mongodb_client_pool);
     105           0 :           if (!mongodb_client) {
     106           0 :             ServiceException se;
     107           0 :             se.errorCode = ErrorCode::SE_MONGODB_ERROR;
     108           0 :             se.message = "Failed to pop a client from MongoDB pool";
     109           0 :             throw se;
     110             :           }
     111             :           auto collection = mongoc_client_get_collection(
     112           0 :               mongodb_client, "url-shorten", "url-shorten");
     113           0 :           if (!collection) {
     114           0 :             ServiceException se;
     115           0 :             se.errorCode = ErrorCode::SE_MONGODB_ERROR;
     116           0 :             se.message = "Failed to create collection user from DB user";
     117           0 :             mongoc_client_pool_push(_mongodb_client_pool, mongodb_client);
     118           0 :             throw se;
     119             :           }
     120             : 
     121           0 :           auto mongo_span = opentracing::Tracer::Global()->StartSpan(
     122             :               "url_mongo_insert_client",
     123           0 :               { opentracing::ChildOf(&span->context()) });
     124             : 
     125             :           mongoc_bulk_operation_t *bulk;
     126             :           bson_t *doc;
     127             :           bson_error_t error;
     128             :           bson_t reply;
     129             :           bool ret;
     130             :           bulk = mongoc_collection_create_bulk_operation_with_opts(
     131           0 :               collection, nullptr);
     132           0 :           for (auto &url : target_urls) {
     133           0 :             doc = bson_new();
     134           0 :             BSON_APPEND_UTF8(doc, "shortened_url", url.shortened_url.c_str());
     135           0 :             BSON_APPEND_UTF8(doc, "expanded_url", url.expanded_url.c_str());
     136           0 :             mongoc_bulk_operation_insert (bulk, doc);
     137           0 :             bson_destroy(doc);
     138             :           }
     139           0 :           ret = mongoc_bulk_operation_execute (bulk, &reply, &error);
     140           0 :           if (!ret) {
     141           0 :             LOG(error) << "MongoDB error: "<< error.message;
     142           0 :             ServiceException se;
     143           0 :             se.errorCode = ErrorCode::SE_MONGODB_ERROR;
     144           0 :             se.message = "Failed to insert urls to MongoDB";
     145           0 :             bson_destroy (&reply);
     146           0 :             mongoc_bulk_operation_destroy(bulk);
     147           0 :             mongoc_collection_destroy(collection);
     148           0 :             mongoc_client_pool_push(_mongodb_client_pool, mongodb_client);
     149           0 :             throw se;
     150             :           }
     151           0 :           bson_destroy (&reply);
     152           0 :           mongoc_bulk_operation_destroy(bulk);
     153           0 :           mongoc_collection_destroy(collection);
     154           0 :           mongoc_client_pool_push(_mongodb_client_pool, mongodb_client);
     155           0 :           mongo_span->Finish();
     156             :           // 新增:成功写入MongoDB日志
     157           0 :           LOG(info) << "Short urls inserted into MongoDB successfully [req_id=" << req_id << ", count=" << target_urls.size() << "]";
     158           0 :         });
     159             : 
     160             :   }
     161             : 
     162         200 :   if (!urls.empty()) {
     163             :     try {
     164           0 :       mongo_future.get();
     165           0 :     } catch (...) {
     166           0 :       LOG(error) << "Failed to upload shortened urls from MongoDB";
     167           0 :       throw;
     168             :     }
     169             :   }
     170             : 
     171         200 :   _return = target_urls;
     172             : 
     173             :   // 新增:方法结束日志
     174         400 :   LOG(info) << "ComposeUrls completed [req_id=" << req_id << ", return count=" << _return.size() << "]";
     175             : 
     176         200 :   span->Finish();
     177             : 
     178         200 : }
     179             : 
     180           0 : void UrlShortenHandler::GetExtendedUrls(
     181             :     std::vector<std::string> &_return,
     182             :     int64_t req_id,
     183             :     const std::vector<std::string> &shortened_id,
     184             :     const std::map<std::string, std::string> &carrier) {
     185             : 
     186             :   // TODO: Implement GetExtendedUrls
     187           0 : }
     188             : 
     189             : }
     190             : 
     191             : 
     192             : 
     193             : #endif //SOCIAL_NETWORK_MICROSERVICES_SRC_URLSHORTENSERVICE_URLSHORTENHANDLER_H_

Generated by: LCOV version 1.12