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

This is a viewer only at the moment see the article on how this works.

To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk

This is a preview from the server running through my markdig pipeline

ASP.NET Email Newsletter Hangfire

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

Monday, 23 September 2024

परिचय

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

परियोजनाएँ

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

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

कुल मिलाकर

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

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

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

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

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

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

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

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

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

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

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]

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

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 प्रारंभ करने से पहले चल रहा है. यह सेवा परिभाषा में जोड़ा गया है...

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

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

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

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

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

dotnet add package Hangfire.AspNetCore
dotnet add package Hangfire.PostgreSql

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

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

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 वर्ग. मैं एक बाद में पोस्ट में अधिक विस्तार में जाना होगा.

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

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

आप इस क्रूस को करने के लिए ऑटो- मैपर / मैपस्टर आदि की तरह आते हुए उपयोग कर सकते हैं। इन्हें प्रयोग करने के लिए भी महत्त्वपूर्ण प्रदर्शन हो सकते हैं । उदाहरण के लिए स्वचालित- मैपपर में है Ift एक्सटेंशन योग्य विधि जो आप क्वैरी में डीएसटो को सीधे मैप करने देता है.

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

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 नक्शे करने के लिए कोड है जो तब नियंत्रकों में प्रयोग किए जाते हैं।

    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
        };
    }

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

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

ऑन्टियम

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

logo

©2024 Scott Galloway