1. हुक्स मेकेनिज़म

Hooks मेकेनिज़म एक तरीका है जिससे डेटाबेस ऑपरेशन्स में विशेष परिवर्तन होने से पहले या उसके बाद अपनी विशेष तरीके से लॉजिक जोड़ा जा सकता है। डेटाबेस स्कीमा को संशोधित करते समय, जैसे नए नोड जोड़ना, नोड्स के बीच की एज़ डिलीट करना, या एक से अधिक नोड्स को डिलीट करना, हम Hooks का उपयोग डेटा मान्यता, लॉगिंग, अनुमति की जांच, या किसी भी विशेष ऑपरेशन के लिए कर सकते हैं। यह डेटा संरचना की संरचना और व्यवसाय नियमों के अनुसार संरचिति को सुनिश्चित करने के लिए महत्वपूर्ण है, साथ ही विकासकों को मूल व्यापार लॉजिक को अत्यंत बदले के बिना अतिरिक्त कार्यक्षमता जोड़ने की अनुमति भी देता है।

2. हुक रजिस्टरेशन मेथड

2.1 ग्लोबल हुक्स और स्थानीय हुक्स

ग्लोबल हुक्स (रनटाइम हुक्स) ग्राफ में सभी प्रकार के ऑपरेशन्स के लिए प्रभावी होते हैं। ये आप्लिकेशन के लिए पूरी तरह से लॉगिंग और मॉनिटरिंग जैसे लॉजिक जोड़ने के लिए उपयुक्त होते हैं। स्थानीय हुक्स (स्कीमा हुक्स) किसी विशेष प्रकार की स्कीमा के भीतर परिभाषित होते हैं और केवल स्कीमा के प्रकार से मेल खाने वाले म्यूटेशन ऑपरेशन्स के लिए होते हैं। स्थानीय हुक्स का उपयोग करने से विशेष नोड प्रकार के सारे लॉजिक को एक ही स्थान में संकलित किया जा सकता है, अर्थात स्कीमा परिभाषा में।

2.2 हुक्स रजिस्टरेशन के चरण

कोड में हुक रजिस्टर करने के लिए सामान्यत:

  1. हुक फ़ंक्शन की परिभाषा। यह फ़ंक्शन ent.Mutator लेता है और एक ent.Mutator वापस करता है। उदाहरण के लिए, एक सरल लॉगिंग हुक बनाना:
logHook := func(next ent.Mutator) ent.Mutator {
    return ent.MutateFunc(func(ctx context.Context, m ent.Mutation) (ent.Value, error) {
        // परिवर्तन ऑपरेशन से पहले लॉग प्रिंट करें
        log.Printf("म्यूटेट होने से पहले: प्रकार=%s, ऑपरेशन=%s\n", m.Type(), m.Op())
        // म्यूटेशन ऑपरेशन करें
        v, err := next.Mutate(ctx, m)
        // परिवर्तन ऑपरेशन के बाद लॉग प्रिंट करें
        log.Printf("म्यूटेट होने के बाद: प्रकार=%s, ऑपरेशन=%s\n", m.Type(), m.Op())
        return v, err
    })
}
  1. क्लाइंट के साथ हुक रजिस्टर करें। ग्लोबल हुक्स के लिए, आप उन्हें क्लाइंट के Use मेथड का उपयोग करके रजिस्टर कर सकते हैं। स्थानीय हुक्स के लिए, आप प्रकार के स्कीमा में Hooks मेथड का उपयोग करके उन्हें रजिस्टर कर सकते हैं।
// एक ग्लोबल हुक रजिस्टर करें
client.Use(logHook)

// एक स्थानीय हुक रजिस्टर करें, केवल यूज़र प्रकार के लिए लागू
client.User.Use(func(next ent.Mutator) ent.Mutator {
    return hook.UserFunc(func(ctx context.Context, m *ent.UserMutation) (ent.Value, error) {
        // विशेष लॉजिक जोड़ें
        // ...
        return next.Mutate(ctx, m)
    })
})
  1. आप कई हुक्स चेन कर सकते हैं, और वे रजिस्टरेशन के क्रम में निष्पादित होंगे।

3. हुक्स के निष्पादन क्रम

हुक्स के निष्पादन क्रम को उनके क्लाइंट के साथ रजिस्टर किए जाने के क्रम द्वारा निर्धारित किया जाता है। उदाहरण के लिए, client.Use(f, g, h) के उदाहरण में, परिवर्तन ऑपरेशन पर f(g(h(...))) के क्रम में निष्पादित होगा। इस उदाहरण में, f पहला हुक्स होगा, उसके बाद g, और अंत में h.

यह एहम नोट करना जरूरी है कि रनटाइम हुक्स (रनटाइम हुक्स) स्कीमा हुक्स (स्कीमा हुक्स) से पहले होते हैं। इसका अर्थ है कि अगर g और h स्कीमा में परिभाषित हुक्स हैं जबकि f को client.Use(...) का उपयोग करके रजिस्टर किया गया है, तो निष्पादन क्रम f(g(h(...))) होगा। इससे यह सुनिश्चित होता है कि ग्लोबल लॉजिक, जैसे लॉगिंग, सभी अन्य हुक्स से पहले निष्पादित होता है।

4. हुक्स के कारण हुए मुद्दों का सामना करना

हुक्स का उपयोग करके डेटाबेस ऑपरेशन्स को अनुकूलित करते समय, हमें अक्सर इंपोर्ट साइकल की समस्या का सामना करना पड़ता है। यह अक्सर तब होता है जब स्कीमा हुक्स का उपयोग करने की कोशिश की जाती है, क्योंकि ent/schema पैकेज डाल ent कोर पैकेज को प्रस्तुत कर सकता है। अगर ent कोर पैकेज भी ent/schema को इम्पोर्ट करने की कोशिश करता है, तो एक सर्कुलर डिपेंडेंसी बन जाती है।

सर्कुलर डिपेंडेंसी के कारण

सर्कुलर डिपेंडेंसी अक्सर स्कीमा परिभाषाओं और उत्पन्न एंटिटी कोड के बीच द्विदिशी प्रत्येकता से उत्पन्न होती है। इसका अर्थ है कि ent/schema ने ent पर निर्भरता (क्योंकि इसे ent फ्रेमवर्क द्वारा प्रदान किए गए प्रकारों का उपयोग करना होता है), जबकि ent द्वारा जनरेट किए गए कोड में ent/schema पर भी निर्भरता होती है (क्योंकि इसमें इसके भीतर परिभाषित स्कीमा जानकारी तक पहुंच करनी होती है)।

घुंटी के सावधानीता विसंगतियों का समाधान

यदि आपको एक घुंटी की सावधानी विसंगति का सामना करना पड़े, तो आप निम्न चरणों का पालन कर सकते हैं:

  1. सबसे पहले, ent/schema में उपयोग किए जाने वाले सभी हुक को टिप्पणी करें।
  2. अगले, ent/schema में परिभाषित कस्टम प्रकारों को एक नए पैकेज में ले जाएं, उदाहरण के लिए, आप 'ent/schema/schematype' नामक एक पैकेज बना सकते हैं।
  3. go generate ./... कमांड चलाएं ताकि ent पैकेज को अपडेट किया जा सके, ताकि वह नए पैकेज पथ की ओर पोइंट करे और स्कीमा में प्रकार संदर्भों को अपडेट करे। उदाहरण के लिए, schema.T को schematype.T में बदलें।
  4. पहले टिप्पणी की गई हुक संदर्भों को अनटिप्ट करें और फिर से go generate ./... कमांड चलाएं। इस समय, कोड जनरेशन त्रुटि के बिना जारी होना चाहिए।

इन चरणों का पालन करके, हम हुक आयात की वजह से होने वाली घुंटी की सावधानी विसंगति को समाधान कर सकते हैं, जिससे स्कीमा का तर्क और हुक्स का अमल समूचित ढंग से आगे बढ़ सके।

5. हुक सहायक फ़ंक्शनों का प्रयोग

ent फ्रेमवर्क हमें हुक के कार्य को नियंत्रित करने में हमारी मदद करने वाले सेट के हुक सहायक फ़ंक्शन प्रदान करता है। नीचे कुछ सामान्य रूप से प्रयोग होने वाले हुक सहायक फ़ंक्शनों के उदाहरण हैं:

// केवल अपडेट वन और डिलीट वन कार्रवाई के लिए हुक ए को केवल चालू करें
hook.On(HookA(), ent.OpUpdateOne|ent.OpDeleteOne)

// निर्माण संचालन के दौरान हुक बी को न करें
hook.Unless(HookB(), ent.OpCreate)

// हुक सी केवल तब चलाएं जब संदर्भ में "स्थिति" क्षेत्र को बदल और "गंदा" क्षेत्र को साफ़ किया जा रहा हो
hook.If(HookC(), hook.And(hook.HasFields("status"), hook.HasClearedFields("dirty")))

// अपडेट (अनेक) कार्रवाई में "पासवर्ड" क्षेत्र को संशोधित करने से बरतावा करें
hook.If(
    hook.FixedError(errors.New("संशोधन बहुत अधिक पर की जा रहा है")),
    hook.And(
        hook.HasOp(ent.OpUpdate),
        hook.Or(
            hook.HasFields("password"),
            hook.HasClearedFields("password"),
        ),
    ),
)

ये सहायक फ़ंक्शन हमें विभिन्न कार्रवाई के लिए हुक की सक्रियता की शर्तों को सटीक ढंग से नियंत्रित करने की अनुमति देते हैं।

6. लेन-हुक्स

लेन-हुक्स विशिष्ट हुक्स को सुनिश्चित करने के लिए अनुमति देता है कि जब एक लेन (लेन) आमदान किया जाता है तो वे कार्यान्वयन किए जाएं (Tx.Commit) या वापस लिया गया है (Tx.Rollback). यह डेटा संरचना और कार्रवाई की अणुपूर्णता सुनिश्चित करने के लिए बहुत उपयोगी है।

लेन-हुक्स का उदाहरण

client.Tx(ctx, func(tx *ent.Tx) error {
    // एक लेन हुक नामंशुल्क करना। - अगले हुकबीफोरकमिट नियंत्रक को प्रक्रिया से पहले चलाया जाएगा।
    tx.OnCommit(func(next ent.Committer) ent.Committer {
        return ent.CommitFunc(func(ctx context.Context, tx *ent.Tx) error {
            // वास्तविक कमिट से पहले की तार्किकता यहाँ रख सकते हैं।
            fmt.Println("कमिट से पहले")
            return next.Commit(ctx, tx)
        })
    })

    // लेन के भीतर एक श्रृंग कार्रवाईयाँ करें...
    
    return nil
})

उपर्युक्त कोड में दिखाया गया है कि कैसे लेन में कमिट से पहले चलाने के लिए एक लेन हुक को पंजीकृत करें। यह हुक डेटाबेस की सभी कार्रवाईयाँ कार्रवाईयाँ कार्रवाईयाँ के बाद और लेन को असली रूप में कमिट किया जाने से पहले चलाया जाएगा।