مجموعة أدوات Node.js لبنى الخدمات الصغيرة
هذه الوحدة مفتوحة المصدر برعاية ودعم Voxgig. |
---|
Seneca عبارة عن مجموعة أدوات لكتابة الخدمات الصغيرة وتنظيم منطق الأعمال لتطبيقك. يمكنك تقسيم تطبيقك إلى "أشياء تحدث"، بدلاً من التركيز على نماذج البيانات أو إدارة التبعيات.
يقدم سينيكا،
مطابقة الأنماط: طريقة مرنة رائعة للتعامل مع متطلبات العمل
استقلالية النقل: إن كيفية وصول الرسائل إلى الخادم الصحيح ليس شيئًا يجب أن تقلق بشأنه
النضج: 8 سنوات من الإنتاج (قبل أن نطلق عليها اسم الخدمات الصغيرة )، ولكن تم التخلص منها ذات مرة بواسطة البرق
بالإضافة إلى: نظام بيئي عميق وواسع من المكونات الإضافية
الكتاب: دليل لتصميم معماريات الخدمات الصغيرة: تاوميكرو
استخدم هذه الوحدة لتحديد الأوامر التي تعمل عن طريق إدخال بعض ملفات JSON، وإرجاع بعض ملفات JSON بشكل اختياري. يتم تحديد الأمر المراد تشغيله عن طريق مطابقة النمط على إدخال JSON. هناك مجموعات مدمجة واختيارية من الأوامر التي تساعدك على إنشاء الحد الأدنى من المنتجات القابلة للتطبيق: تخزين البيانات، وإدارة المستخدم، والمنطق الموزع، والتخزين المؤقت، والتسجيل، وما إلى ذلك. ويمكنك تحديد المنتج الخاص بك عن طريق تقسيمه إلى مجموعة من الأوامر - " الأشياء التي تحدث". هذا إلى حد كبير.
إذا كنت تستخدم هذه الوحدة، وتحتاج إلى مساعدة، فيمكنك:
إذا كنت جديدًا في Seneca بشكل عام، فيرجى إلقاء نظرة على senecajs.org. لدينا كل شيء بدءًا من البرامج التعليمية وحتى نماذج التطبيقات لمساعدتك في البدء بالعمل بسرعة.
يمكن قراءة مصدر Seneca بطريقة مشروحة عن طريق تشغيل npm run annotate
. سيتم إنشاء نسخة مشروحة من كل ملف في ./docs/
.
للتثبيت عبر npm،
npm install seneca
'use strict'
var Seneca = require ( 'seneca' )
// Functionality in seneca is composed into simple
// plugins that can be loaded into seneca instances.
function rejector ( ) {
this . add ( 'cmd:run' , ( msg , done ) => {
return done ( null , { tag : 'rejector' } )
} )
}
function approver ( ) {
this . add ( 'cmd:run' , ( msg , done ) => {
return done ( null , { tag : 'approver' } )
} )
}
function local ( ) {
this . add ( 'cmd:run' , function ( msg , done ) {
this . prior ( msg , ( err , reply ) => {
return done ( null , { tag : reply ? reply . tag : 'local' } )
} )
} )
}
// Services can listen for messages using a variety of
// transports. In process and http are included by default.
Seneca ( )
. use ( approver )
. listen ( { type : 'http' , port : '8260' , pin : 'cmd:*' } )
Seneca ( )
. use ( rejector )
. listen ( 8270 )
// Load order is important, messages can be routed
// to other services or handled locally. Pins are
// basically filters over messages
function handler ( err , reply ) {
console . log ( err , reply )
}
Seneca ( )
. use ( local )
. act ( 'cmd:run' , handler )
Seneca ( )
. client ( { port : 8270 , pin : 'cmd:run' } )
. client ( { port : 8260 , pin : 'cmd:run' } )
. use ( local )
. act ( 'cmd:run' , handler )
Seneca ( )
. client ( { port : 8260 , pin : 'cmd:run' } )
. client ( { port : 8270 , pin : 'cmd:run' } )
. use ( local )
. act ( 'cmd:run' , handler )
// Output
// null { tag: 'local' }
// null { tag: 'approver' }
// null { tag: 'rejector' }
للتشغيل بشكل طبيعي، على سبيل المثال، في حاوية، استخدم
$ node microservice.js
(حيث أن microservice.js
هو ملف نصي يستخدم Seneca). يتم إخراج السجلات بتنسيق JSON حتى تتمكن من إرسالها إلى خدمة التسجيل.
للتشغيل في وضع الاختبار، باستخدام سجلات التصحيح الكاملة التي يمكن قراءتها بواسطة الإنسان، استخدم:
$ node microservice.js --seneca.test
بحيث لا يهم،
طالما أن بعض الأوامر يمكنها التعامل مع مستند JSON معين، فأنت جيد.
هنا مثال:
var seneca = require ( 'seneca' ) ( )
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
var rate = 0.23
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
seneca . act ( { cmd : 'salestax' , net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
في هذا الكود، عندما يرى سينيكا النمط {cmd:'salestax'}
، فإنه ينفذ الوظيفة المرتبطة بهذا النمط، والتي تحسب ضريبة المبيعات. لا يوجد شيء مميز في العقار cmd
. إنها ببساطة الخاصية التي نريد مطابقة النمط. يمكنك البحث عن foo
لجميع اهتمامات سينيكا! ياه!
يضيف الأسلوب seneca.add
نمطًا جديدًا، والوظيفة التي سيتم تنفيذها عند حدوث هذا النمط.
يقبل الأسلوب seneca.act
كائنًا، ويقوم بتشغيل الأمر المطابق، إن وجد.
من أين يأتي معدل ضريبة المبيعات؟ دعونا نحاول مرة أخرى:
seneca . add ( { cmd : 'config' } , function ( msg , done ) {
var config = { rate : 0.23 }
var value = config [ msg . prop ]
done ( null , { value : value } )
} )
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
seneca . act ( { cmd : 'config' , prop : 'rate' } , function ( err , result ) {
var rate = parseFloat ( result . value )
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
} )
seneca . act ( { cmd : 'salestax' , net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
يوفر لك أمر config
التكوين الخاص بك. يعد هذا أمرًا رائعًا لأنه لا يهم من أين يتم الحصول على التكوين - من نظام الملفات المشفر أو قاعدة البيانات أو خدمة الشبكة أو أي شيء آخر. هل كان عليك تحديد واجهة برمجة التطبيقات المجردة لإنجاز هذا العمل؟ لا.
هناك القليل ولكن الكثير من الإسهاب هنا، ألا تعتقد ذلك؟ دعونا إصلاح ذلك:
seneca . act ( 'cmd:salestax,net:100' , function ( err , result ) {
console . log ( result . total )
} )
بدلاً من توفير كائن، يمكنك توفير سلسلة باستخدام نموذج مختصر من JSON. في الواقع، يمكنك توفير كليهما:
seneca . act ( 'cmd:salestax' , { net : 100 } , function ( err , result ) {
console . log ( result . total )
} )
هذه طريقة ملائمة جدًا للجمع بين بيانات النمط والمعلمة .
الطريقة لبناء أنظمة Node.js هي بناء الكثير من العمليات الصغيرة. إليك حديث رائع يشرح لماذا يجب عليك القيام بذلك: Programmer Anarchy.
سينيكا يجعل هذا الأمر سهلاً حقًا. دعونا نضع التكوين على الشبكة في عمليته الخاصة:
seneca . add ( { cmd : 'config' } , function ( msg , done ) {
var config = { rate : 0.23 }
var value = config [ msg . prop ]
done ( null , { value : value } )
} )
seneca . listen ( )
تقوم طريقة listen
بتشغيل خادم ويب يستمع إلى رسائل JSON. عند وصولها، يتم إرسالها إلى مثيل Seneca المحلي، ويتم تنفيذها كإجراءات بالطريقة العادية. ثم يتم إرجاع النتيجة إلى العميل كرد على طلب HTTP. يمكن لـ Seneca أيضًا الاستماع إلى الإجراءات عبر ناقل الرسائل.
يظل تطبيقك لرمز التكوين كما هو .
يبدو رمز العميل كما يلي:
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
seneca . act ( { cmd : 'config' , prop : 'rate' } , function ( err , result ) {
var rate = parseFloat ( result . value )
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
} )
seneca . client ( )
seneca . act ( 'cmd:salestax,net:100' , function ( err , result ) {
console . log ( result . total )
} )
من جانب العميل، فإن استدعاء seneca.client()
يعني أن Seneca سيرسل أي إجراءات لا يمكن مطابقتها محليًا عبر الشبكة. في هذه الحالة، سيطابق خادم التكوين نمط cmd:config
ويعيد بيانات التكوين.
مرة أخرى، لاحظ أن رمز ضريبة المبيعات الخاص بك لا يتغير . لا تحتاج إلى معرفة من أين يأتي التكوين، أو من يوفره، أو كيف.
يمكنك القيام بذلك مع كل أمر.
الشيء المتعلق بمتطلبات العمل هو أنهم لا يحترمون الفطرة السليمة أو المنطق أو البنية المنظمة. العالم الحقيقي فوضوي.
في مثالنا، لنفترض أن بعض البلدان لديها معدل ضريبة مبيعات واحد، والبعض الآخر لديه معدل متغير، والذي يعتمد إما على المنطقة المحلية أو فئة المنتج.
هذا هو الرمز. سنقوم بحذف رمز التكوين لهذا المثال.
// fixed rate
seneca . add ( { cmd : 'salestax' } , function ( msg , done ) {
var rate = 0.23
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
// local rates
seneca . add ( { cmd : 'salestax' , country : 'US' } , function ( msg , done ) {
var state = {
'NY' : 0.04 ,
'CA' : 0.0625
// ...
}
var rate = state [ msg . state ]
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
// categories
seneca . add ( { cmd : 'salestax' , country : 'IE' } , function ( msg , done ) {
var category = {
'top' : 0.23 ,
'reduced' : 0.135
// ...
}
var rate = category [ msg . category ]
var total = msg . net * ( 1 + rate )
done ( null , { total : total } )
} )
seneca . act ( 'cmd:salestax,net:100,country:DE' , function ( err , result ) {
console . log ( 'DE: ' + result . total )
} )
seneca . act ( 'cmd:salestax,net:100,country:US,state:NY' , function ( err , result ) {
console . log ( 'US,NY: ' + result . total )
} )
seneca . act ( 'cmd:salestax,net:100,country:IE,category:reduced' , function ( err , result ) {
console . log ( 'IE: ' + result . total )
} )
في هذه الحالة، يمكنك توفير تطبيقات مختلفة لأنماط مختلفة. يتيح لك هذا عزل التعقيد في أماكن محددة جيدًا. ويعني أيضًا أنه يمكنك التعامل مع الحالات الخاصة بسهولة بالغة.
تشجع منظمة Senecajs المشاركة. إذا كنت تشعر أنه يمكنك المساعدة بأي شكل من الأشكال، سواء كان ذلك من خلال الإبلاغ عن الأخطاء أو الوثائق أو الأمثلة أو الاختبارات الإضافية أو الميزات الجديدة، فلا تتردد في إنشاء مشكلة، أو الأفضل من ذلك، إرسال طلب سحب. لمزيد من المعلومات حول المساهمة، يرجى الاطلاع على دليل المساهمة الخاص بنا.
لإجراء الاختبارات محليًا،
npm run test
للحصول على تقرير التغطية
npm run coverage; open docs/coverage.html
حقوق الطبع والنشر (ج) 2010-2018 لريتشارد رودجر ومساهمين آخرين؛ مرخص تحت معهد ماساتشوستس للتكنولوجيا .