# सेवा सेवा भाग 2 - रीफ्रेक्टिंग (और एक छोटी सी मशीन आग)

# परिचय

में [इस श्रृंखला का 1 भाग](/blog/anewslettersubscriptionservicept1) मैंने तुम्हें दिखाया कि कैसे मैंने एक नया समाचार समाचार पत्र (अंग्रेज़ी) पृष्ठ बनाया. इस भाग में मैं इस बात को कवर करूंगा कि किस तरह मैं सेवा और मॉडलों को शामिल करने के लिए हल फिर से तैयार हो जाएगा वेबसाइट परियोजना के बीच (बहुत ज्यादा से कम से कम) और प्रबंधक सेवा परियोजना (बहुत ही कम से कम है).

[TOC]

<!--category-- ASP.NET, Hangfire, Email Newsletter -->
<datetime class="hidden">2024-09-23T10:45</datetime>

# परियोजनाएँ

मूल रूप से मैं केवल एक ही था, एक एकल, एकल परियोजना जिसमें वेबसाइट के लिए सभी कोड शामिल थे. यह छोटी - छोटी अनुप्रयोगों के लिए एक उपयुक्‍त समीप है, यह आपको संचार करने, निर्माण करने और हल चलाने के लिए एक सरल तरीक़ा देता है; उन सभी का लिहाज़ करने के लिए लिहाज़ किया जाता है । हालांकि जैसे आप एक समाधान पर स्केल आप अपनी परियोजना को अलग करने के लिए बाहर होना शुरू करना चाहते हैं चिंता और आसान परीक्षण के लिए अनुमति देने के लिए, नेविगेशन (बहुत से अधिक बिट के साथ बहुत बड़ी परियोजना) ले जाया जा सकता है।
इसके अतिरिक्‍त सारिणीबद्ध सेवा मेरे लिए समझ आता है क्योंकि मैं इस पर निगरानी कर सकता हूँ एक अलग डॉकर पात्र के रूप में मुझे वेबसाइट को अद्यतन करने के लिए अनुमति देता है बिना समयबद्ध कार्यक्रम फिर से प्रारंभ करने के लिए.

ऐसा करने के लिए मैंने 5 परियोजनाओं में तर्कसंगतता से ध्यान दिया । यह शायद अनुप्रयोग में एक आम तरीका है.

मैं अब इन में से प्रत्येक के लिए परीक्षण परियोजना जोड़ सकते हैं और अकेलेपन में उन्हें परीक्षण कर सकते हैं. यह एक बड़ा लाभ है क्योंकि यह मुझे पूरी अनुप्रयोग चलाने की जरूरत के बिना सेवाओं को जाँचने की अनुमति देता है.

## कुल मिलाकर

यह परियोजना एक असुरक्षित है. नेटटीसी कोर (8) वेब परियोजना है, यह सभी उपयोगकर्ता को पृष्ठों को दिखाने के लिए नियंत्रक व दृश्य रखता है.

## संदर्भ के बारे में सबसे कम जानकारी दी गयी है ।

यह मेरे मुख्य संदर्भ परिभाषा है जो इस डाटाबेस के साथ संवाद करने के लिए प्रयोग में आता है. ईएफ कोर डीबी संदर्भ को मिलाकर।

## सेवा के लिए बहुत - से भाई - बहनों का जोश कम हो गया ।

यह मुख्य क्लास परियोजना है जो कि सभी सेवाओं को समाहित करता है जो डाटाबेस / ईमेल सेवा के साथ सम्बद्ध करती हैं /.

## बहुत कम. ( g02 3 / 22)

यह एक वर्ग पुस्तकालय परियोजना है जो सभी साझा मॉडलों को रखता है जो कि सबसे अधिक अनपेक्षित और अतिवादी दोनों द्वारा इस्तेमाल किए जाते हैं।

## ज़्यादातर लोगों ने ऐसा ही किया ।

यह एक वेब अनुप्रयोग है जो हैंग आग सेवा को नियंत्रित करता है जो कि ई- मेल भेजने के लिए सारिणीबद्ध कार्य को चलाता है तथा अंत बिन्दुओं को नियंत्रित करने के लिए.

इस संरचना को नीचे दिखाया गया है.
आप देख सकते हैं कि शेड्यूलर सेवा और मुख्य विशेष रूप से प्रतिनिधित्व सिर्फ आरंभिक सेटअप के लिए डीबी संदर्भ क्लास का प्रयोग करें.

```mermaid
graph LR
  Mostlylucid[Mostlylucid] --> |Intialize| Mostlylucid_DbContext[Mostlylucid.DbContext]
  Mostlylucid[Mostlylucid] --> Mostlylucid_Shared[Mostlylucid.Shared]
  Mostlylucid[Mostlylucid] --> Mostlylucid_Services[Mostlylucid.Services]
  
  Mostlylucid_DbContext[Mostlylucid.DbContext] --> Mostlylucid_Shared[Mostlylucid.Shared]
  
  Mostlylucid_Services[Mostlylucid.Services] --> Mostlylucid_DbContext[Mostlylucid.DbContext]
  Mostlylucid_Services[Mostlylucid.Services] --> Mostlylucid_Shared[Mostlylucid.Shared]
  


  Mostlylucid_SchedulerService[Mostlylucid.SchedulerService] --> Mostlylucid_Shared[Mostlylucid.Shared]
  Mostlylucid_SchedulerService[Mostlylucid.SchedulerService] --> |Intialize|Mostlylucid_DbContext[Mostlylucid.DbContext]
  Mostlylucid_SchedulerService[Mostlylucid.SchedulerService] --> Mostlylucid_Services[Mostlylucid.Services]

```

जैसे ही मैं किसी एक्सटेंशन विधि का उपयोग डाटाबेस को सेटिंग के लिए करता हूं.

```csharp
public static class Setup
{
    public static void SetupDatabase(this IServiceCollection services, IConfiguration configuration,
        IWebHostEnvironment env, string applicationName="mostlylucid")
    {
        services.AddDbContext<IMostlylucidDBContext, MostlylucidDbContext>(options =>
        {
            if (env.IsDevelopment())
            {
                options.EnableDetailedErrors(true);
                options.EnableSensitiveDataLogging(true);
            }
            var connectionString = configuration.GetConnectionString("DefaultConnection");
            var connectionStringBuilder = new NpgsqlConnectionStringBuilder(connectionString)
            {
                ApplicationName = applicationName
            };
            options.UseNpgsql(connectionStringBuilder.ConnectionString);
        });
    }
}
```

इस विधि से अतिरिक्त शीर्ष स्तर परियोजना में डीबी संदर्भ परियोजना पर कोई निर्भरता है.

नोट: यह महत्वपूर्ण है कि एक प्रजाति स्थिति से बचने के लिए महत्वपूर्ण है जब आप Dbabons शुरू कर रहे हैं (सामान्य रूप से अगर आप इस करने के लिए चल रहा है) सिर्फ यहाँ मैं अपने डॉकर में एक muldiod फ़ाइल जोड़ने के लिए, सुनिश्चित करने के लिए कि सबसे बड़े sdddd परियोजना ऊपर है और मेरे bududrodriddrdridrod प्रारंभ करने से पहले चल रहा है. यह सेवा परिभाषा में जोड़ा गया है...

```dockerfile
  depends_on:
      - mostlylucid 
  healthcheck:
      test: ["CMD", "curl", "-f", "http://mostlylucid:80/healthy"]
      interval: 30s
      timeout: 10s
      retries: 5
```

आप इसे अन्य तरीकों से भी पूरा कर सकते हैं, उदाहरण के लिए जब मैं एक ही ऐप के कई उदाहरणों पर चल रहा है मैं एक लॉक फ्लैग सेट करने के लिए प्रयोग किया है जो प्रत्येक उदाहरण है कि उत्प्रवासन / अन्य कार्य चलाने से पहले केवल एक ही बार में चलना चाहिए.

# हैंग फ़ाय सेटअप

मैंने कहा कि जब तक मेरे पास आसान - सी चीज़ होती है, तब तक मैं अपनी सारणी का इस्तेमाल करने के लिए करता हूँ ।

इस शेड्यूलर सर्विस परियोजना में मैंने निम्न एनयूएओ पैकेजों को जोड़ा.

```bash
dotnet add package Hangfire.AspNetCore
dotnet add package Hangfire.PostgreSql
```

इसका मतलब है कि मैं अनुसूचित कार्यों के लिए मेरे दुकान के रूप में पोस्टग्रेस का उपयोग कर सकते हैं।

अब मैं हैंग अप मैं अपने सारिणीबद्ध कार्य जोड़ने के लिए शुरू कर सकते हैं.

```csharp
public static class JobInitializer
{
    private const string AutoNewsletterJob = "AutoNewsletterJob";
    private const string DailyNewsletterJob = "DailyNewsletterJob";
    private const string WeeklyNewsletterJob = "WeeklyNewsletterJob";
    private const string MonthlyNewsletterJob = "MonthlyNewsletterJob";
    public static void InitializeJobs(this IApplicationBuilder app)
    {
      var scope=  app.ApplicationServices.CreateScope();
        var recurringJobManager = scope.ServiceProvider.GetRequiredService<RecurringJobManager>();
      
        recurringJobManager.AddOrUpdate<NewsletterSendingService>(AutoNewsletterJob,  x =>  x.SendNewsletter(SubscriptionType.EveryPost), Cron.Hourly);
        recurringJobManager.AddOrUpdate<NewsletterSendingService>(DailyNewsletterJob,  x =>  x.SendNewsletter(SubscriptionType.Daily), "0 17 * * *");
        recurringJobManager.AddOrUpdate<NewsletterSendingService>(WeeklyNewsletterJob,  x =>  x.SendNewsletter(SubscriptionType.Weekly), "0 17 * * *");
        recurringJobManager.AddOrUpdate<NewsletterSendingService>(MonthlyNewsletterJob,  x => x.SendNewsletter(SubscriptionType.Monthly), "0 17 * * *");
    }
}
```

यहाँ आप मैं प्रत्येक के लिए एक नौकरी है देखते हैं `SubscriptionType` जो एक झंडा है जो निर्धारित करता है कि किस तरह अखबार भेजा जाता है. मैं उपयोग `Cron` कार्य की आवृत्ति सेट करने के लिए वर्ग.

मैं दोनों महीने और साप्ताहिक सदस्यता के लिए दिन के लिए विकल्प है के रूप में मैं 17: 00 (5pm) के लिए समय सेट के रूप में यह एक अच्छा समय है अमेरिका में दिन के बाद और अमेरिका में शुरू करने के लिए एक अच्छा समय है।
मेरे पास एक नौकरी भी है जो हर घंटे उन लोगों को भेजने के लिए दौड़ती है जिन्होंने हर पोस्ट में अपील की है.

यह तब होता है जब इसे एक में बुलाया जाता है `SendNewsletter` विधि में `NewsletterSendingService` वर्ग. मैं एक बाद में पोस्ट में अधिक विस्तार में जाना होगा.

# स्केल्स तथा नक्शािंग

मैं उपयोग [डीटीओ](https://en.wikipedia.org/wiki/Data_transfer_object) मेरे अनुप्रयोग की परतों के बीच डेटा ले जाने के लिए. यह जटिल रूप से जोड़ता है क्योंकि मुझे नक्शे की ज़रूरत है (करीब दो बार) Dtotototos और फिर stototocs को देखने के लिए (और)। लेकिन, मुझे लगता है कि चिन्ताओं के इस अलगाव के मूल्य के रूप में यह मिल गया है...... यह मुझे यूआई को प्रभावित करने के बिना मूल डेटा संरचना को बदलने की अनुमति देता है.

आप इस क्रूस को करने के लिए ऑटो- मैपर / मैपस्टर आदि की तरह आते हुए उपयोग कर सकते हैं। इन्हें प्रयोग करने के लिए भी महत्त्वपूर्ण प्रदर्शन हो सकते हैं । उदाहरण के लिए स्वचालित- मैपपर में है [Ift एक्सटेंशन योग्य](https://docs.automapper.org/en/stable/Queryable-Extensions.html) विधि जो आप क्वैरी में डीएसटो को सीधे मैप करने देता है.

लेकिन इस मामले में मैंने फैसला किया कि मैं नक्शेरे विस्तार को जोड़ूँगा, जहाँ मुझे ज़रूरत थी । यह मुझे प्रत्येक स्तर के लिए फिल्टरों पर अधिक नियंत्रण रखने देता है (लेकिन अधिक काम है, विशेष रूप से अगर आपके पास बहुत संपत्ति है).

```csharp
public static class BlogPostEntityMapper
{
   public static BlogPostDto ToDto(this BlogPostEntity entity, string[] languages = null)
    {
        return new BlogPostDto
        {
            Id = entity.Id.ToString(),
            Title = entity.Title,
            Language = entity.LanguageEntity?.Name,
            Markdown = entity.Markdown,
            UpdatedDate = entity.UpdatedDate.DateTime,
            HtmlContent = entity.HtmlContent,
            PlainTextContent = entity.PlainTextContent,
            Slug = entity.Slug,
            WordCount = entity.WordCount,
            PublishedDate = entity.PublishedDate.DateTime,
            Languages = languages ?? Array.Empty<string>()
        };
    }
}
```

यहाँ पर आप देख सकते हैं कि मैं मैप करता हूँ `BlogPostEntity` मेरे मुख्य को `BlogPostDto` जो मेरा ट्रांसपर ऑब्जेक्ट है.  
उद्देश्य है कि सामने अंत सेवाओं के बारे में कुछ नहीं जानता एंटिटी वस्तु के बारे में और मूल डेटा संरचना से 'बस्तित' हैं।

इन शीर्ष स्तर सेवाओं में मैं तो इन Dtototos नक्शे करने के लिए कोड है जो तब नियंत्रकों में प्रयोग किए जाते हैं।

```csharp
    public static PostListModel ToPostListModel(this BlogPostDto dto)
    {
        return new PostListModel
        {
            Id = dto.Id,
            Title = dto.Title,
            Language = dto.Language,
            UpdatedDate = dto.UpdatedDate.DateTime,
            Slug = dto.Slug,
            WordCount = dto.WordCount,
            PublishedDate = dto.PublishedDate,
            Languages = dto.Languages
        };
    }
    
    public static BlogPostViewModel ToViewModel(this BlogPostDto dto)
    {
        return new BlogPostViewModel
        {
            Id = dto.Id,
            Title = dto.Title,
            Language = dto.Language,
            Markdown = dto.Markdown,
            UpdatedDate = dto.UpdatedDate.DateTime,
            HtmlContent = dto.HtmlContent,
            PlainTextContent = dto.PlainTextContent,
            Slug = dto.Slug,
            WordCount = dto.WordCount,
            PublishedDate = dto.PublishedDate,
            Languages = dto.Languages
        };
    }
```

एक बार फिर, एक नक्शा उपकरण इस्तेमाल करने से इस स्लेट कोड (और त्रुटियाँ कम) से बच सकता है लेकिन मुझे लगता है कि इस उदाहरण में मेरे लिए यह तरीका अच्छा है.

अब मेरे पास ये सभी मॉडल हैं सेट मैं उन्हें इस्तेमाल करने के लिए नियंत्रण को जोड़ने के तरीके शुरू कर सकते हैं।
मैं अगले भाग में इस प्रवाह को कवर करेंगे.

# ऑन्टियम

अब हमारे पास इमारत है जिसे हम अपने उपभोक्ताओं को पत्रिकाएँ देने की अनुमति दे रहे हैं ।
इस रीफ्रेक्टिंग थोड़ा दर्दनाक था लेकिन यह सबसे अधिक परियोजनाओं के लिए जीवन का एक तथ्य है. जब आवश्यक हो सरल और कच्चे कवरेज को जोड़ें तो शुरू करें.
भविष्य पोस्ट इस के बाकी पोस्टों को कवर करेंगे, जिसमें मेरे प्रयोग पर एक पालन अप शामिल है [फ्लंट मेल] ईमेल तथा होस्ट सेवा भेजने के लिए... और शायद एक छोटे से अधिक हैंग आग.