ViennaNET: بیک اینڈ کے لیے لائبریریوں کا ایک سیٹ۔ حصہ 2

Raiffeisenbank .NET ڈویلپر کمیونٹی ViennaNET کے مواد کا مختصر جائزہ لینا جاری رکھے ہوئے ہے۔ اس بارے میں کہ ہم اس تک کیسے اور کیوں پہنچے، آپ پہلا حصہ پڑھ سکتے ہیں۔.

اس آرٹیکل میں، ہم تقسیم شدہ لین دین، قطاروں اور ڈیٹا بیس کے ساتھ کام کرنے کے لیے ابھی تک زیر غور لائبریریوں سے گزریں گے، جو ہمارے GitHub ذخیرے (ذرائع یہاں ہیں) ، اور یہاں نوگیٹ پیکجز.

ViennaNET: بیک اینڈ کے لیے لائبریریوں کا ایک سیٹ۔ حصہ 2

ViennaNET.Sagas

جب کوئی پروجیکٹ DDD اور مائیکرو سروس آرکیٹیکچر پر سوئچ کرتا ہے، پھر جب کاروباری منطق کو مختلف سروسز میں تقسیم کیا جاتا ہے، تو تقسیم شدہ لین دین کے طریقہ کار کو لاگو کرنے کی ضرورت سے متعلق ایک مسئلہ پیدا ہوتا ہے، کیونکہ بہت سے منظرنامے اکثر ایک ساتھ کئی ڈومینز کو متاثر کرتے ہیں۔ آپ اس طرح کے میکانزم سے مزید تفصیل سے واقف ہو سکتے ہیں، مثال کے طور پر، کتاب "مائیکرو سروسز پیٹرنز" میں، کرس رچرڈسن.

اپنے پروجیکٹس میں، ہم نے ایک سادہ لیکن مفید طریقہ کار نافذ کیا ہے: ایک ساگا، یا اس کے بجائے آرکیسٹریشن پر مبنی کہانی۔ اس کا خلاصہ درج ذیل ہے: ایک خاص کاروباری منظر نامہ ہے جس میں مختلف خدمات میں ترتیب وار آپریشن کرنا ضروری ہے، اور اگر کسی بھی قدم پر کوئی مسئلہ پیدا ہوتا ہے تو، تمام پچھلے مراحل کے لیے رول بیک طریقہ کار کو کال کرنا ضروری ہے، جہاں یہ ہے۔ فراہم کی. اس طرح، کہانی کے اختتام پر، کامیابی سے قطع نظر، ہم تمام ڈومینز میں مستقل ڈیٹا حاصل کرتے ہیں۔

ہمارا نفاذ اب بھی اس کی بنیادی شکل میں ہے اور دیگر خدمات کے ساتھ تعامل کے کسی بھی طریقے کے استعمال سے منسلک نہیں ہے۔ اسے استعمال کرنا مشکل نہیں ہے: صرف بیس خلاصہ کلاس SagaBase<T> کی اولاد بنائیں، جہاں T آپ کی سیاق و سباق کی کلاس ہے جس میں آپ ساگا کے کام کرنے کے لیے ضروری ابتدائی ڈیٹا کے ساتھ ساتھ کچھ درمیانی نتائج بھی محفوظ کر سکتے ہیں۔ سیاق و سباق کی مثال عملدرآمد کے دوران تمام مراحل سے گزر جائے گی۔ ساگا بذات خود ایک سٹیٹ لیس کلاس ہے، اس لیے ضروری انحصار حاصل کرنے کے لیے مثال کو سنگلٹن کے طور پر DI میں رکھا جا سکتا ہے۔

مثال اشتہار:

public class ExampleSaga : SagaBase<ExampleContext>
{
  public ExampleSaga()
  {
    Step("Step 1")
      .WithAction(c => ...)
      .WithCompensation(c => ...);
	
    AsyncStep("Step 2")
      .WithAction(async c => ...);
  }
}

مثال کال:

var saga = new ExampleSaga();
var context = new ExampleContext();
await saga.Execute(context);

مختلف نفاذ کی مکمل مثالیں دیکھی جا سکتی ہیں۔ یہاں اور اس کے ساتھ اسمبلی میں ٹیسٹ.

ViennaNET.Orm۔*

Nhibernate کے ذریعے مختلف ڈیٹا بیس کے ساتھ کام کرنے کے لیے لائبریریوں کا ایک سیٹ۔ ہم Liquibase کا استعمال کرتے ہوئے DB-First اپروچ استعمال کرتے ہیں، اس لیے صرف ایک ریڈی میڈ ڈیٹا بیس میں ڈیٹا کے ساتھ کام کرنے کی فعالیت ہے۔

ViennaNET.Orm.Seedwork и ViennaNET.Orm - بالترتیب بنیادی انٹرفیس اور ان کے نفاذ پر مشتمل اہم اسمبلیاں۔ آئیے ان کے مواد کو مزید تفصیل سے دیکھتے ہیں۔

انٹرفیس IEntityFactoryService اور اس کا نفاذ EntityFactoryService ڈیٹابیس کے ساتھ کام کرنے کے لیے بنیادی نقطہ آغاز ہیں، چونکہ یونٹ آف ورک، مخصوص اداروں کے ساتھ کام کرنے کے لیے ذخیرے، نیز کمانڈز اور براہ راست ایس کیو ایل کے سوالات یہاں بنائے گئے ہیں۔ کبھی کبھی ڈیٹا بیس کے ساتھ کام کرنے کے لیے کلاس کی صلاحیتوں کو محدود کرنا آسان ہوتا ہے، مثال کے طور پر، صرف ڈیٹا کو پڑھنے کی صلاحیت فراہم کرنا۔ ایسے معاملات کے لیے IEntityFactoryService ایک اجداد - انٹرفیس ہے IEntityRepositoryFactory، جو صرف ذخیرے بنانے کے طریقہ کار کا اعلان کرتا ہے۔

ڈیٹا بیس تک براہ راست رسائی کے لیے فراہم کنندہ کا طریقہ کار استعمال کیا جاتا ہے۔ ہر DBMS جسے ہم اپنی ٹیموں میں استعمال کرتے ہیں اس کا اپنا نفاذ ہوتا ہے: ViennaNET.Orm.MSSQL, ViennaNET.Orm.Oracle, ViennaNET.Orm.SQLite, ViennaNET.Orm.PostgreSql.

ایک ہی وقت میں، کئی فراہم کنندگان کو ایک ہی وقت میں ایک درخواست میں رجسٹر کیا جا سکتا ہے، جو مثال کے طور پر، ایک سروس کے فریم ورک کے اندر، بنیادی ڈھانچے میں ترمیم کے لیے بغیر کسی لاگت کے، سے مرحلہ وار منتقلی کی اجازت دیتا ہے۔ ایک سے دوسرے DBMS۔ مطلوبہ کنکشن کو منتخب کرنے کا طریقہ کار اور، اس وجہ سے، مخصوص ہستی کی کلاس کے لیے فراہم کنندہ (جس کے لیے ڈیٹا بیس ٹیبلز پر نقشہ لکھا جاتا ہے) کو BoundedContext کلاس میں ہستی کے اندراج کے ذریعے لاگو کیا جاتا ہے (ڈومین اداروں کو رجسٹر کرنے کا طریقہ موجود ہے) یا اس کے جانشین ApplicationContext (ایپلی کیشن اداروں کو رجسٹر کرنے کے طریقے، براہ راست درخواستیں اور کمانڈز پر مشتمل ہے)، جہاں کنفیگریشن سے کنکشن شناخت کنندہ کو بطور دلیل قبول کیا جاتا ہے:

"db": [
  {
    "nick": "mssql_connection",
    "dbServerType": "MSSQL",
    "ConnectionString": "...",
    "useCallContext": true
  },
  {
    "nick": "oracle_connection",
    "dbServerType": "Oracle",
    "ConnectionString": "..."
  }
],

مثال ApplicationContext:

internal sealed class DbContext : ApplicationContext
{
  public DbContext()
  {
    AddEntity<SomeEntity>("mssql_connection");
    AddEntity<MigratedSomeEntity>("oracle_connection");
    AddEntity<AnotherEntity>("oracle_connection");
  }
}

اگر کنکشن ID کی وضاحت نہیں کی گئی ہے، تو پھر "ڈیفالٹ" نام کا کنکشن استعمال کیا جائے گا۔

ڈیٹا بیس ٹیبل پر اداروں کی براہ راست نقشہ سازی معیاری NHibernate ٹولز کا استعمال کرتے ہوئے لاگو کی جاتی ہے۔ آپ ایکس ایم ایل فائلوں اور کلاسز کے ذریعے تفصیل استعمال کر سکتے ہیں۔ یونٹ ٹیسٹ میں سٹب ریپوزٹریوں کی آسان تحریر کے لیے، ایک لائبریری موجود ہے۔ ViennaNET.TestUtils.Orm.

ViennaNET.Orm.* استعمال کرنے کی مکمل مثالیں مل سکتی ہیں۔ یہاں.

ViennaNET.Messaging.*

قطاروں کے ساتھ کام کرنے کے لیے لائبریریوں کا ایک سیٹ۔

قطاروں کے ساتھ کام کرنے کے لیے، مختلف ڈی بی ایم ایس کے ساتھ ایک ہی نقطہ نظر کا انتخاب کیا گیا تھا، یعنی لائبریری کے ساتھ کام کرنے کے معاملے میں زیادہ سے زیادہ ممکنہ متحد نقطہ نظر، قطع نظر اس کے کہ قطار مینیجر کا استعمال کیا گیا ہو۔ کتب خانہ ViennaNET.Messaging اس اتحاد کے لیے بالکل ذمہ دار ہے، اور ViennaNET.Messaging.MQSeriesQueue, ViennaNET.Messaging.RabbitMQQueue и ViennaNET.Messaging.KafkaQueue IBM MQ، RabbitMQ اور Kafka کے لیے بالترتیب اڈاپٹر کے نفاذ پر مشتمل ہے۔

قطاروں کے ساتھ کام کرتے وقت، دو عمل ہوتے ہیں: پیغام وصول کرنا اور اسے بھیجنا۔

وصول کرنے پر غور کریں۔ یہاں 2 اختیارات ہیں: مسلسل سننے کے لیے اور ایک پیغام وصول کرنے کے لیے۔ قطار کو مسلسل سننے کے لیے، آپ کو پہلے وراثت میں ملی پروسیسر کلاس کی وضاحت کرنی ہوگی۔ IMessageProcessor، جو آنے والے پیغام پر کارروائی کے لیے ذمہ دار ہو گا۔ اگلا، اسے ایک مخصوص قطار سے "لنک" ہونا چاہیے؛ یہ اندراج کے ذریعے کیا جاتا ہے۔ IQueueReactorFactory ترتیب سے قطار کے شناخت کنندہ کی نشاندہی کرنا:

"messaging": {
    "ApplicationName": "MyApplication"
},
"rabbitmq": {
    "queues": [
      {
        "id": "myQueue",
        "queuename": "lalala",
        ...
      }
    ]
},

سننا شروع کرنے کی مثال:

_queueReactorFactory.Register<MyMessageProcessor>("myQueue");
var queueReactor = queueReactorFactory.CreateQueueReactor("myQueue");
queueReactor.StartProcessing();

پھر، جب سروس شروع ہوتی ہے اور طریقہ سننا شروع کرنے کے لیے کہا جاتا ہے، مخصوص قطار سے تمام پیغامات متعلقہ پروسیسر کے پاس جائیں گے۔

فیکٹری انٹرفیس میں ایک پیغام وصول کرنے کے لیے IMessagingComponentFactory ایک طریقہ ہے CreateMessageReceiverجو ایک وصول کنندہ بنائے گا جو اس کے لیے مخصوص قطار سے پیغام کا انتظار کر رہا ہے:

using (var receiver = _messagingComponentFactory.CreateMessageReceiver<TestMessage>("myQueue"))
{
    var message = receiver.Receive();
}

پیغام بھیجنے کے لیے آپ کو ایک ہی استعمال کرنے کی ضرورت ہے IMessagingComponentFactory اور پیغام بھیجنے والا بنائیں:

using (var sender = _messagingComponentFactory.CreateMessageSender<MyMessage>("myQueue"))
{
    sender.SendMessage(new MyMessage { Value = ...});
}

پیغام کو سیریلائز کرنے اور ڈی سیریلائز کرنے کے لیے تین ریڈی میڈ آپشنز ہیں: صرف ٹیکسٹ، XML اور JSON، لیکن اگر ضروری ہو تو، آپ آسانی سے اپنے انٹرفیس پر عمل درآمد کر سکتے ہیں۔ IMessageSerializer и IMessageDeserializer.

ہم نے ہر قطار مینیجر کی منفرد صلاحیتوں کو محفوظ رکھنے کی کوشش کی ہے، جیسے ViennaNET.Messaging.MQSeriesQueue آپ کو نہ صرف متن بھیجنے کی اجازت دیتا ہے، بلکہ بائٹ پیغامات بھی، اور ViennaNET.Messaging.RabbitMQQueue روٹنگ اور آن دی فلائی قطار کی حمایت کرتا ہے۔ RabbitMQ کے لیے ہمارا اڈاپٹر ریپر بھی کچھ RPC کی علامت کو نافذ کرتا ہے: ہم ایک پیغام بھیجتے ہیں اور ایک خاص عارضی قطار سے جواب کا انتظار کرتے ہیں، جو صرف ایک جوابی پیغام کے لیے بنائی گئی ہے۔

یہاں بنیادی کنکشن باریکیوں کے ساتھ قطاروں کو استعمال کرنے کی ایک مثال.

ViennaNET.CallContext

ہم قطاروں کا استعمال نہ صرف مختلف سسٹمز کے درمیان انضمام کے لیے کرتے ہیں بلکہ ایک ہی ایپلی کیشن کے مائیکرو سروسز کے درمیان رابطے کے لیے بھی کرتے ہیں، مثال کے طور پر، ایک کہانی کے اندر۔ اس کی وجہ سے پیغام کے ساتھ معاون ڈیٹا منتقل کرنے کی ضرورت پیش آئی جیسے صارف کا لاگ ان، اختتام سے آخر تک لاگنگ کے لیے شناخت کنندہ کی درخواست، سورس آئی پی ایڈریس اور اتھارٹی ڈیٹا۔ اس ڈیٹا کی فارورڈنگ کو لاگو کرنے کے لیے، ہم نے ایک لائبریری تیار کی۔ ViennaNET.CallContext، جو آپ کو سروس میں داخل ہونے والی درخواست سے ڈیٹا ذخیرہ کرنے کی اجازت دیتا ہے۔ اس معاملے میں، درخواست کیسے کی گئی، قطار کے ذریعے یا Http کے ذریعے، کوئی فرق نہیں پڑتا۔ پھر، باہر جانے والی درخواست یا پیغام بھیجنے سے پہلے، ڈیٹا کو سیاق و سباق سے لیا جاتا ہے اور ہیڈر میں رکھا جاتا ہے۔ اس طرح، اگلی سروس معاون ڈیٹا حاصل کرتی ہے اور اسے اسی طرح منظم کرتی ہے۔

آپ کی توجہ کا شکریہ، ہم آپ کے تبصروں اور درخواستوں کے منتظر ہیں!

ماخذ: www.habr.com

نیا تبصرہ شامل کریں