diff --git a/Jenkinsfile b/Jenkinsfile index 22f6a89..13a75ee 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -10,28 +10,15 @@ build('limiter-proto', 'docker-host') { runStage('load pipeline') { env.JENKINS_LIB = "build_utils/jenkins_lib" pipeDefault = load("${env.JENKINS_LIB}/pipeDefault.groovy") + pipeJavaProto = load("${env.JENKINS_LIB}/pipeJavaProto.groovy") gitUtils = load("${env.JENKINS_LIB}/gitUtils.groovy") } pipeDefault() { - runStage('compile') { - withGithubPrivkey { - sh "make submodules" - sh "make wc_compile" - } + sh "make wc_compile" } - - // Java - runStage('Execute build container') { - withCredentials([[$class: 'FileBinding', credentialsId: 'java-maven-settings.xml', variable: 'SETTINGS_XML']]) { - if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME.startsWith('epic/')) { - sh 'make SETTINGS_XML=${SETTINGS_XML} BRANCH_NAME=${BRANCH_NAME} wc_java.deploy' - } else { - sh 'make SETTINGS_XML=${SETTINGS_XML} wc_java.compile' - } - } - } - + env.skipSonar = 'true' + pipeJavaProto() } } diff --git a/Makefile b/Makefile index 3e1c8c1..883d7b8 100644 --- a/Makefile +++ b/Makefile @@ -7,13 +7,12 @@ UTILS_PATH := build_utils TEMPLATES_PATH := . # Name of the service -SERVICE_NAME := limiter_proto +SERVICE_NAME := limiter-proto # Build image tag to be used -BUILD_IMAGE_TAG := eee42f2ca018c313190bc350fe47d4dea70b6d27 +BUILD_IMAGE_TAG := b04c5291d101132e53e578d96e1628d2e6dab0c0 CALL_ANYWHERE := \ - all submodules rebar-update compile clean distclean \ - java.compile java.deploy + all submodules compile clean distclean CALL_W_CONTAINER := $(CALL_ANYWHERE) @@ -30,10 +29,7 @@ $(SUBTARGETS): %/.git: % submodules: $(SUBTARGETS) -rebar-update: - $(REBAR) update - -compile: submodules +compile: $(REBAR) compile clean: @@ -41,43 +37,6 @@ clean: distclean: $(REBAR) clean -a - rm -rfv _build _builds _cache _steps _temp + rm -rfv _build -# Java - -ifdef SETTINGS_XML -DOCKER_RUN_OPTS = -v $(SETTINGS_XML):$(SETTINGS_XML) -DOCKER_RUN_OPTS += -e SETTINGS_XML=$(SETTINGS_XML) -endif - -ifdef LOCAL_BUILD -DOCKER_RUN_OPTS += -v $$HOME/.m2:/home/$(UNAME)/.m2:rw -endif - -COMMIT_HASH := $(shell git --no-pager log -1 --pretty=format:"%h") -NUMBER_COMMITS := $(shell git rev-list --count HEAD) - -JAVA_PKG_VERSION := 1.$(NUMBER_COMMITS)-$(COMMIT_HASH) - -ifdef BRANCH_NAME -ifeq "$(findstring epic,$(BRANCH_NAME))" "epic" -JAVA_PKG_VERSION := $(JAVA_PKG_VERSION)-epic -endif -endif - -MVN = mvn -s $(SETTINGS_XML) -Dpath_to_thrift="$(THRIFT)" -Dcommit.number="$(NUMBER_COMMITS)" - -java.compile: java.settings - $(MVN) compile - -java.deploy: java.settings - $(MVN) versions:set versions:commit -DnewVersion="$(JAVA_PKG_VERSION)" && \ - $(MVN) deploy - -java.install: java.settings - $(MVN) clean && \ - $(MVN) versions:set versions:commit -DnewVersion="$(JAVA_PKG_VERSION)" && \ - $(MVN) install - -java.settings: - $(if $(SETTINGS_XML),, echo "SETTINGS_XML not defined"; exit 1) +include $(UTILS_PATH)/make_lib/java_proto.mk \ No newline at end of file diff --git a/build_utils b/build_utils index b9b18f3..e131872 160000 --- a/build_utils +++ b/build_utils @@ -1 +1 @@ -Subproject commit b9b18f3ee375aa5fd105daf57189ac242c40f572 +Subproject commit e1318727d4d0c3e48f5122bf3197158b6695f50e diff --git a/proto/base.thrift b/proto/base.thrift new file mode 100644 index 0000000..4704f8f --- /dev/null +++ b/proto/base.thrift @@ -0,0 +1,89 @@ +namespace java com.rbkmoney.limiter.base +namespace erlang limiter_base + +/** + * Отметка во времени согласно RFC 3339. + * + * Строка должна содержать дату и время в UTC в следующем формате: + * `2016-03-22T06:12:27Z`. + */ +typedef string Timestamp + +/** Идентификатор объекта */ +typedef string ID +typedef i32 ObjectID + +/** Идентификатор аккаунта */ +typedef i64 AccountID + +/** Идентификатор некоторого события */ +typedef i64 EventID + +struct EventRange { + 1: optional EventID after + 2: optional i32 limit +} + +/** ISO 4217 */ +typedef string CurrencySymbolicCode + +/** Сумма в минимальных денежных единицах. */ +typedef i64 Amount + +/** Значение ассоциации */ +typedef string Tag + +/** Внешний идентификатор (идентификатор в системе клиента) для сущностей системы. */ +typedef ID ExternalID + +typedef i64 DataRevision +typedef i64 PartyRevision + +/** Непрозрачный для участника общения набор данных */ +typedef binary Opaque + +/** + * Идентификатор валюты + * + * Украдено из https://github.com/rbkmoney/damsel/blob/8235b6f6/proto/domain.thrift#L912 + */ +struct CurrencyRef { 1: required CurrencySymbolicCode symbolic_code } + +/** + * Объём денежных средств + * + * Украдено из https://github.com/rbkmoney/damsel/blob/8235b6f6/proto/domain.thrift#L70 + */ +struct Cash { + 1: required Amount amount + 2: required CurrencyRef currency +} + +struct CashRange { + 1: required CashBound upper + 2: required CashBound lower +} + +union CashBound { + 1: Cash inclusive + 2: Cash exclusive +} + +struct AmountRange { + 1: required AmountBound upper + 2: required AmountBound lower +} + +union AmountBound { + 1: Amount inclusive + 2: Amount exclusive +} + +/** + * Исключение, сигнализирующее о непригодных с точки зрения бизнес-логики входных данных + */ +exception InvalidRequest { + /** Список пригодных для восприятия человеком ошибок во входных данных */ + 1: required list errors +} + diff --git a/proto/configurator.thrift b/proto/configurator.thrift new file mode 100644 index 0000000..9753e3b --- /dev/null +++ b/proto/configurator.thrift @@ -0,0 +1,36 @@ +include "base.thrift" +include "limiter.thrift" +include "limiter_config.thrift" + +namespace java com.rbkmoney.limiter.configurator +namespace erlang limiter_cfg + +typedef base.ID LimitName +typedef limiter_config.LimitConfigID LimitConfigID +typedef limiter_config.ShardSize ShardSize +typedef limiter_config.LimitConfig LimitConfig +typedef limiter_config.LimitBodyType LimitBodyType + +struct LimitCreateParams { + 1: required LimitConfigID id + 2: required base.Timestamp started_at + /** Идентификатор набора настроек создаваемого лимата, в будущем идентификатор заменит структура конфигурации */ + 3: optional LimitName name + 4: optional string description + 5: optional LimitBodyType body_type +} + +exception LimitConfigNameNotFound {} +exception LimitConfigNotFound {} + +service Configurator { + LimitConfig Create(1: LimitCreateParams params) throws ( + 1: LimitConfigNameNotFound e1, + 2: base.InvalidRequest e2 + ) + + LimitConfig Get(1: LimitConfigID id) throws ( + 1: LimitConfigNotFound e1, + 2: base.InvalidRequest e2 + ) +} diff --git a/proto/limiter.thrift b/proto/limiter.thrift index a56f017..1e6c7fe 100644 --- a/proto/limiter.thrift +++ b/proto/limiter.thrift @@ -1,165 +1,63 @@ +include "base.thrift" +include "limiter_context.thrift" + namespace java com.rbkmoney.limiter namespace erlang limiter -include "proto/shumpune.thrift" -include "proto/base.thrift" - -typedef string LimitID -typedef string PlanID -typedef i64 BatchID -typedef i64 AccountID -typedef string LimitRef -typedef i64 DomainRevision - -typedef shumpune.Clock Clock -typedef shumpune.Balance Balance -typedef base.InvalidRequest InvalidRequest +typedef base.ID LimitChangeID +typedef base.ID LimitID +typedef base.ID PartyID +typedef base.ID ShopID +typedef base.ID WalletID +typedef base.ID IdentityID +typedef limiter_context.LimitContext LimitContext /** -* Описывает типы лимитов: -* cash - валютный лимит - ассоциирован с изменением сумм в какой-либо валюте -* count - счетный лимит - ассоциирован с количеством каких-либо операций в системе -*/ -enum LimitType { - cash - count + * https://en.wikipedia.org/wiki/Vector_clock + **/ +struct VectorClock { + 1: required base.Opaque state } /** -* Структура данных, описывающая свойства сублимита: -* account_id -идентификатор аккаунта ассоциированного с временным действием сублимита -* time_range - время действия сублимита -*/ -struct Sublimit { - 1: required AccountID account_id - 2: required LimitTimeRange time_range +* Структура, позволяющая установить причинно-следственную связь операций внутри сервиса +**/ +union Clock { + 1: VectorClock vector } -/** -* Структура данных, описывающая свойства лимита: -* id -идентификатор машины лимита -* ref - идентификатор лимита в domain конфигурации -* domain_revision - ревизия конфигурации -* type - тип лимита -* sublimits - сублимиты лимита -* description - описание (неизменяемо после создания лимита) -*/ struct Limit { 1: required LimitID id - 2: required LimitRef ref - 3: required DomainRevision domain_revision - 4: required LimitType type - 5: required list sublimits - 6: optional string description + 2: required base.Amount amount + 3: optional base.Timestamp creation_time + 4: optional string description } -/** -* Описывает одно изменение лимита в системе, может быть следующих типов: -* cash - изменение валютного лимита -* count - изменение счетного лимита -*/ -union LimitUnit { - 1: LimitUnitCash cash - 2: LimitUnitCount count +struct LimitChange { + 1: required LimitID id + 2: required LimitChangeID change_id } -struct LimitUnitCash { +exception LimitNotFound {} +exception LimitChangeNotFound {} +exception ForbiddenOperationAmount { 1: required base.Amount amount - 2: required base.CurrencySymbolicCode currency_sym_code + 2: required base.AmountRange allowed_range } -struct LimitUnitCount { - 1: required base.Amount amount -} - -/** -* Описывает батч - набор изменений лимита, служит единицей атомарности операций в системе: -* id - идентификатор набора, уникален в пределах плана -* units - набор изменений лимита -*/ -struct LimitBatch { - 1: required BatchID id - 2: required list units -} - -/** - * План состоит из набора батчей, который можно пополнить, подтвердить или отменить: - * id - идентификатор плана, уникален в рамках системы - * batch_list - набор батчей, связанный с данным планом -*/ -struct LimitPlan { - 1: required PlanID id - 2: required list batch_list -} - -/** -* Описывает параметры создания лимита: -* ref - идентификатор лимита в domain конфигурации -* domain_revision - ревизия конфигурации -* create_time - время старта нового временного интервала лимита -*/ -struct LimitCreateParams { - 1: required LimitRef ref - 2: required DomainRevision domain_revision - 3: required base.Timestamp create_time -} - -/** -* Описывает единицу изменения плана: -* id - id плана, к которому применяется данное изменение -* batch - набор изменений, который нужно добавить в план -* create_params - если такого лимита нет или срок дейтсвия сублимита истек, то эти параметры -* будут использованы чтобы проинициализировать новый лимит/сублимит. - Так как мы не знаем существует ли лимит, то всегда прикладываем эти параметры. -*/ -struct LimitPlanChange { - 1: required PlanID id - 2: required LimitBatch batch - 3: required LimitCreateParams create_params -} - -/** -* Описывает время действия лимита: -* start_time - начало действия лимита -* end_time - конец, если не бесконечно -*/ -struct LimitTimeRange { - 1: required base.Timestamp start_time - 2: optional base.Timestamp end_time -} - -/** -* Описывает точку во времени жизни лимита: -* clock - clock состояния счета аккаунта, привязанного к сублимиту -* time_range - время действия сублимита, чтобы можно было его найти в лимите -*/ -struct LimitClock { - 1: required Clock clock - 2: required LimitTimeRange time_range -} - -exception LimitNotFound { - 1: required LimitID limit_id -} - -exception PlanNotFound { - 1: required PlanID plan_id -} - -/** -* Возникает в случае, если переданы некорректные параметры в одном или нескольких изменениях лимита -*/ -exception InvalidLimitParams { - 1: required map wrong_limits -} - -exception ClockInFuture {} - -service Accounter { - LimitClock Hold(1: LimitPlanChange plan_change) throws (1: InvalidLimitParams e1, 2: base.InvalidRequest e2) - LimitClock CommitPlan(1: LimitPlan plan) throws (1: InvalidLimitParams e1, 2: base.InvalidRequest e2) - LimitClock RollbackPlan(1: LimitPlan plan) throws (1: InvalidLimitParams e1, 2: base.InvalidRequest e2) - LimitPlan GetPlan(1: PlanID id) throws (1: PlanNotFound e1) - Limit GetLimitByID(1: LimitID id) throws (1:LimitNotFound e1) - Balance GetBalanceByID(1: LimitID id, 2: LimitClock clock) throws (1:LimitNotFound e1, 2: ClockInFuture e2) +service Limiter { + Limit Get(1: LimitID id, 2: Clock clock, 3: LimitContext context) throws ( + 1: LimitNotFound e1, + 2: base.InvalidRequest e2 + ) + Clock Hold(1: LimitChange change, 2: Clock clock, 3: LimitContext context) throws ( + 1: LimitNotFound e1, + 3: base.InvalidRequest e2 + ) + Clock Commit(1: LimitChange change, 2: Clock clock, 3: LimitContext context) throws ( + 1: LimitNotFound e1, + 2: LimitChangeNotFound e2, + 3: base.InvalidRequest e3, + 4: ForbiddenOperationAmount e4 + ) } diff --git a/proto/limiter_config.thrift b/proto/limiter_config.thrift new file mode 100644 index 0000000..57e6603 --- /dev/null +++ b/proto/limiter_config.thrift @@ -0,0 +1,87 @@ +/** + * Машина хранящая конфигурацию лимита + */ + +namespace java com.rbkmoney.limiter.config +namespace erlang limiter_config + +include "base.thrift" +include "time_range.thrift" + +/// Domain + +typedef base.ID LimitConfigID +typedef base.Timestamp Timestamp +typedef base.Amount ShardSize +typedef base.CurrencySymbolicCode CurrencySymbolicCode + +struct LimitConfig { + 1: required LimitConfigID id + 2: required string processor_type + 3: required Timestamp created_at + 4: required LimitBodyType body_type + 5: required Timestamp started_at + 6: required ShardSize shard_size + 7: required time_range.TimeRangeType time_range_type + 11: required LimitContextType context_type + 8: optional LimitType type + 9: optional LimitScope scope + 10: optional string description +} + +union LimitBodyType { + 1: LimitBodyTypeAmount amount + 2: LimitBodyTypeCash cash +} + +struct LimitBodyTypeAmount {} +struct LimitBodyTypeCash { + 1: required CurrencySymbolicCode currency +} + + +union LimitType { + 1: LimitTypeTurnover turnover +} + +struct LimitTypeTurnover {} + +union LimitScope { + 1: LimitScopeGlobal scope_global + 2: LimitScopeType scope +} + +struct LimitScopeGlobal {} + +union LimitScopeType { + 1: LimitScopeTypeParty party + 2: LimitScopeTypeShop shop + 3: LimitScopeTypeWallet wallet + 4: LimitScopeTypeIdentity identity +} + +struct LimitScopeTypeParty {} +struct LimitScopeTypeShop {} +struct LimitScopeTypeWallet {} +struct LimitScopeTypeIdentity {} + +union LimitContextType { + 1: LimitContextTypePaymentProcessing payment_processing +} + +struct LimitContextTypePaymentProcessing {} + +/// LimitConfig events + +struct TimestampedChange { + 1: required base.Timestamp occured_at + 2: required Change change +} + +union Change { + 1: CreatedChange created +} + +struct CreatedChange { + 1: required LimitConfig limit_config +} diff --git a/proto/limiter_context.thrift b/proto/limiter_context.thrift new file mode 100644 index 0000000..cb636dd --- /dev/null +++ b/proto/limiter_context.thrift @@ -0,0 +1,103 @@ +include "base.thrift" + +namespace java com.rbkmoney.limiter.context +namespace erlang limiter_context + +typedef base.ID ID + +struct LimitContext { + 1: optional ContextPaymentProcessing payment_processing +} + +/** + * Контекст, получаемый из сервисов, реализующих один из интерфейсов протокола + * https://github.com/rbkmoney/damsel/tree/master/proto/payment_processing.thrift + * (например invoicing в hellgate) + */ +struct ContextPaymentProcessing { + 1: optional PaymentProcessingOperation op + 2: optional Invoice invoice +} + +union PaymentProcessingOperation { + 1: PaymentProcessingOperationInvoice invoice + 2: PaymentProcessingOperationInvoiceAdjustment invoice_adjustment + 3: PaymentProcessingOperationInvoicePayment invoice_payment + 4: PaymentProcessingOperationInvoicePaymentAdjustment invoice_payment_adjustment + 5: PaymentProcessingOperationInvoicePaymentRefund invoice_payment_refund + 6: PaymentProcessingOperationInvoicePaymentChargeback invoice_payment_chargeback +} + +struct PaymentProcessingOperationInvoice {} +struct PaymentProcessingOperationInvoiceAdjustment {} +struct PaymentProcessingOperationInvoicePayment {} +struct PaymentProcessingOperationInvoicePaymentAdjustment {} +struct PaymentProcessingOperationInvoicePaymentRefund {} +struct PaymentProcessingOperationInvoicePaymentChargeback {} + +struct Invoice { + 1: optional ID id + 2: optional ID owner_id + 3: optional ID shop_id + 4: optional base.Cash cost + 5: optional base.Timestamp created_at + 6: optional InvoicePayment effective_payment + 7: optional InvoiceAdjustment effective_adjustment +} + +struct InvoiceAdjustment { + 1: optional ID id +} + +struct InvoicePayment { + 1: optional ID id + 2: optional ID owner_id + 3: optional ID shop_id + 4: optional base.Cash cost + 11: optional base.Cash capture_cost + 5: optional base.Timestamp created_at + 6: optional InvoicePaymentFlow flow + 7: optional Payer payer + 8: optional InvoicePaymentAdjustment effective_adjustment + 9: optional InvoicePaymentRefund effective_refund + 10: optional InvoicePaymentChargeback effective_chargeback +} + +/** + * Процесс выполнения платежа. + */ +union InvoicePaymentFlow { + 1: InvoicePaymentFlowInstant instant + 2: InvoicePaymentFlowHold hold +} + +struct InvoicePaymentFlowInstant {} +struct InvoicePaymentFlowHold {} + +union Payer { + 1: PaymentResourcePayer payment_resource + 2: CustomerPayer customer + 3: RecurrentPayer recurrent +} + +struct PaymentResourcePayer {} +struct CustomerPayer {} +struct RecurrentPayer {} + +struct InvoicePaymentAdjustment { + 1: optional ID id + 2: optional base.Timestamp created_at +} + +struct InvoicePaymentRefund { + 1: optional ID id + 2: optional base.Cash cost + 3: optional base.Timestamp created_at +} + +struct InvoicePaymentChargeback { + 1: optional ID id + 2: optional base.Timestamp created_at + 3: optional base.Cash levy + 4: optional base.Cash body +} diff --git a/proto/limiter_range.thrift b/proto/limiter_range.thrift new file mode 100644 index 0000000..92fa85e --- /dev/null +++ b/proto/limiter_range.thrift @@ -0,0 +1,49 @@ +/** + * Машина хранящая временные интервалы + */ + +namespace java com.rbkmoney.limiter.range +namespace erlang limiter_range + +include "base.thrift" +include "time_range.thrift" + +/// Domain + +typedef base.ID LimitRangeID +typedef base.Timestamp Timestamp + +struct LimitRange { + 1: required LimitRangeID id + 2: required time_range.TimeRangeType type + 3: required Timestamp created_at + 4: optional base.CurrencySymbolicCode currency +} + +struct LimitRangeState { + 1: required LimitRangeID id + 2: required time_range.TimeRangeType type + 3: required Timestamp created_at + 4: optional list ranges + 5: optional base.CurrencySymbolicCode currency +} + +/// LimitRange events + +struct TimestampedChange { + 1: required base.Timestamp occured_at + 2: required Change change +} + +union Change { + 1: CreatedChange created + 2: TimeRangeCreatedChange time_range_created +} + +struct CreatedChange { + 1: required LimitRange limit_range +} + +struct TimeRangeCreatedChange { + 1: required time_range.TimeRange time_range +} diff --git a/proto/time_range.thrift b/proto/time_range.thrift new file mode 100644 index 0000000..91b9237 --- /dev/null +++ b/proto/time_range.thrift @@ -0,0 +1,43 @@ +/** + * Временные интервалы + */ + +namespace java com.rbkmoney.limiter.range.time +namespace erlang time_range + +include "base.thrift" + +/// Domain + +typedef base.ID LimitRangeID +typedef base.AccountID AccountID +typedef base.Timestamp Timestamp +typedef base.Amount IntervalAmount + +union TimeRangeType { + 1: TimeRangeTypeCalendar calendar + 2: TimeRangeTypeInterval interval +} + +union TimeRangeTypeCalendar { + 1: TimeRangeTypeCalendarYear year + 2: TimeRangeTypeCalendarMonth month + 3: TimeRangeTypeCalendarWeek week + 4: TimeRangeTypeCalendarDay day +} + +struct TimeRangeTypeCalendarYear {} +struct TimeRangeTypeCalendarMonth {} +struct TimeRangeTypeCalendarWeek {} +struct TimeRangeTypeCalendarDay {} + +struct TimeRangeTypeInterval { + 1: required IntervalAmount amount // in sec +} + +struct TimeRange { + 1: required Timestamp upper + 2: required Timestamp lower + 3: optional AccountID account_id_from + 4: optional AccountID account_id_to +} diff --git a/rebar.config b/rebar.config index 91d1c0f..176a440 100644 --- a/rebar.config +++ b/rebar.config @@ -25,16 +25,7 @@ warn_missing_spec_all ]}. -{deps, [ - {msgpack_proto, - {git, "git@github.com:rbkmoney/msgpack-proto.git", - {branch, "master"}} - }, - {shumpune_proto, - {git, "git@github.com:rbkmoney/shumpune-proto.git", - {branch, "master"}} - } -]}. +{deps, []}. %% XRef checks {xref_checks, [ @@ -44,9 +35,6 @@ deprecated_functions ]}. -%% Tests -{cover_enabled, true}. - %% Dialyzer static analyzing {dialyzer, [ {warnings, [ @@ -73,8 +61,5 @@ {thrift_compiler_opts, [ {in_dir, "proto"}, - {in_files, [ - "limiter.thrift" - ]}, - {gen, "erlang:scoped_typenames"} + {gen, "erlang:scoped_typenames,app_prefix=lim"} ]}. diff --git a/rebar.lock b/rebar.lock index d6f2163..57afcca 100644 --- a/rebar.lock +++ b/rebar.lock @@ -1,8 +1 @@ -[{<<"msgpack_proto">>, - {git,"git@github.com:rbkmoney/msgpack-proto.git", - {ref,"b558b0d9a91f2130e241bd186db171aee3e81e36"}}, - 0}, - {<<"shumpune_proto">>, - {git,"git@github.com:rbkmoney/shumpune-proto.git", - {ref,"4c87f03591cae3dad41504eb463d962af536b1ab"}}, - 0}]. +[].