1. ہکس میکینزم
ہکس
میکینزم ایک طریقہ ہے جو ہمیں ڈیٹا بیس آپریشنز میں مخصوص تبدیلیاں ہونے سے پہلے یا بعد میں کسٹم لاجک شامل کرنے کے لیے فراہم کرتا ہے۔ جب ہم ڈیٹا بیس سکیما کو تبدیل کرتے ہیں، جیسے کہ نؤوں کی نوڈز شامل کرنا، نوڈز کے درمیان تعلقات کو حذف کرنا، یا متعدد نوڈز کو حذف کرنا، ہم ہکس
کا استعمال کرتے ہیں تاکہ ہم اس میں ڈیٹا کی تصدیق، لاگ ریکارڈنگ، اجازت کی چیکس یا کسٹم آپریشن کر سکیں۔ یہ معاون ہے تاکہ ہم ڈیٹا کی تسلسل اور کام کی قوانین کے مطابقت کو یقینی بنا سکیں، جبکہ یہ ساتھ ہی ساتھ ڈویلپرز کو اصل کاروباری منطق کو تبدیل کئے بغیر اضافی فنکشنلٹی شامل کرنے کا مواقع فراہم کرتا ہے۔
2. ہک رجسٹریشن میتھڈ
2.1 گلوبل ہکس اور لوکل ہکس
گلوبل ہکس (رن ٹائم ہکس
) گراف کے تمام قسم کے آپریشنز کے لیے فعال ہوتے ہیں۔ یہ سارے ایپلیکیشن میں منطق شامل کرنے کے لیے مناسب ہوتے ہیں، جیسے کہ لاگنگ اور مانیٹرنگ۔ لوکل ہکس (اسکیما ہکس
) مخصوص قسم سکیما کے اندر تعریف کیے جاتے ہیں اور صرف اُن تبدیلیوں پر لاگو ہوتے ہیں جو اُن سکیما کی قسم سے مشابہت رکھتی ہوں۔ لوکل ہکس استعمال کرنے سے مخصوص نوڈ کی ساری منطق ایک ہی جگہ میں جمع ہوتی ہے، یعنی سکیما کی تعریف میں۔
2.2 ہکس رجسٹریشن میں اقدامات
کوڈ میں ہک رجسٹر کرنا عموماً مندرجہ ذیل اقدامات کو شامل کرتا ہے:
- ہک فنکشن کی التعریف کرنا۔ یہ فنکشن ایک
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("Before mutating: Type=%s, Operation=%s\n", m.Type(), m.Op())
// تبدیلی کا عمل انجام دیں
v, err := next.Mutate(ctx, m)
// تبدیلی کے عمل کے بعد لاگز پرنٹ کریں
log.Printf("After mutating: Type=%s, Operation=%s\n", m.Type(), m.Op())
return v, err
})
}
- کلائنٹ کے ساتھ ہک رجسٹر کریں۔ گلوبل ہکس کے لیے، آپ انہیں کلائنٹ کے
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)
})
})
- آپ متعدد ہکس چین کرسکتے ہیں، اور وہ رجسٹر کرنے کے ترتیب کے تابع میں انجام دیئے جائیں گے۔
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
پر منحصر ہوتا ہے (کیونکہ اسے اس کے اندر معین کی تعریف کی معلومات تک رسائی چاہئیے۔)
دائری تعلقات کا حل کرنا
اگر آپ دائری تعلقات کی خرابی سے کچھ سامنا کرتے ہیں، تو آپ مندرجہ ذیل اقدامات کر سکتے ہیں:
- سب سے پہلے ،
ent/schema
میں استعمال کردہ ہوکس پر تبصرہ لگائیں۔ - اگلے ،
ent/schema
میں تعریف شدہ شخصی اقسام کو ایک نئی پیکیج میں منتقل کریں، مثلاً آپent/schema/schematype
نام کی ایک پیکیج بنا سکتے ہیں۔ -
go generate ./...
کمانڈ چلائیں تاکہent
پیکیج کو اپ ڈیٹ کیا جائے، تاکہ وہ نئے پیکیج کا راستہ دیکھے، اور اسکی سکیما میں قسم کے حوالوں کو اپ ڈیٹ کریں۔ مثلاً ،schema.T
کوschematype.T
میں تبدیل کریں۔ - پہلے تبصرہ کردہ ہوکس حوالوں کو آن تبصرہ کریں اور دوبارہ
go generate ./...
کمانڈ کو دوبارہ چلائیں۔ اس نقطے پر ، کوڈ جنریشن بغیر خرابیوں کے آگے بڑھنا چاہئے گا۔
ان اقدامات کی پیروی کر کے، آپ ہمیشہ کے لئے ہمزاد داخلی خرابی کو حل کر سکتے ہیں جو ہکس کے درآمدات سے پیدا ہوئی ہوتی ہے، اور ہمارے پلان اور ہکس کے تنظیم کا حسبہ اٹھانا یقینی بنا سکتے ہیں۔
5. ہک مددگار فنکشنز کا استعمال
ent
فریم ورک ہمیں ایک سیٹ کے ہک مددگار فنکشنز فراہم کرتا ہے، جو ہمیں ہکس کی اجراء وقت کو کنٹرول کرنے میں مدد فراہم کر سکتے ہیں۔ ذیل میں کچھ عام طور پر استعمال ہونے والے ہک مددگار فنکشنز کی مثالیں ہیں:
// صرف UpdateOne اور DeleteOne عمل کے لئے ہک A کو کال کریں
hook.On(HookA(), ent.OpUpdateOne|ent.OpDeleteOne)
// ہک B کو Create عمل کے دوران نہیں چلائیں
hook.Unless(HookB(), ent.OpCreate)
// ہک C صرف جب Mutation "status" فیلڈ میں تبدیلی لارہی ہو اور "dirty" فیلڈ کو صاف کر رہی ہو تو چلائیں
hook.If(HookC(), hook.And(hook.HasFields("status"), hook.HasClearedFields("dirty")))
// Update (multiple) عمل کے دوران "password" فیلڈ کو تبدیل نہیں کیا جاسکتا ہے
hook.If(
hook.FixedError(errors.New("password cannot be edited on update many")),
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 {
// ٹرانزیکشن ہکس رجسٹر کرنا - ہکBeforeCommit مکمل ہونے سے پہلے چلایا جائے گا
tx.OnCommit(func(next ent.Committer) ent.Committer {
return ent.CommitFunc(func(ctx context.Context, tx *ent.Tx) error {
// واقعی مکمل ہونے سے پہلے منطق یہاں رکھا جا سکتا ہے۔
fmt.Println("Before commit")
return next.Commit(ctx, tx)
})
})
// ٹرانزیکشن کے اندر سلسلہ مندرج عملیات کو کریں...
return nil
})
اوپر دیے گؓے کوڈ میں دکھایا گیا ہے کہ کیسے ایک ٹرانزیکشن مکمل ہونے سے پہلے ایک ٹرانزیکشن ہک رجسٹر کیا جائے گا۔ یہ ہک واقعی تمام ڈیٹا بیس عملیات کے بعد چلایا جائے گا اور ٹرانزیکشن واقعی مکمل ہونے سے پہلے۔