{ - ListgetWithPolicies(Collectionids); - - void disable(long id); -} diff --git a/src/main/java/dev/vality/hooker/dao/SimpleRetryPolicyDao.java b/src/main/java/dev/vality/hooker/dao/SimpleRetryPolicyDao.java deleted file mode 100644 index a116b30..0000000 --- a/src/main/java/dev/vality/hooker/dao/SimpleRetryPolicyDao.java +++ /dev/null @@ -1,11 +0,0 @@ -package dev.vality.hooker.dao; - -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.retry.impl.simple.SimpleRetryPolicyRecord; - -/** - * Created by jeckep on 17.04.17. - */ -public interface SimpleRetryPolicyDao { - void update(SimpleRetryPolicyRecord record) throws DaoException; -} diff --git a/src/main/java/dev/vality/hooker/dao/TaskDao.java b/src/main/java/dev/vality/hooker/dao/TaskDao.java deleted file mode 100644 index a8e41c2..0000000 --- a/src/main/java/dev/vality/hooker/dao/TaskDao.java +++ /dev/null @@ -1,19 +0,0 @@ -package dev.vality.hooker.dao; - - -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.model.Task; - -import java.util.List; -import java.util.Map; - -/** - * Created by jeckep on 13.04.17. - */ -public interface TaskDao { - void remove(long queueId, long messageId); - - void removeAll(long queueId) throws DaoException; - - Map > getScheduled() throws DaoException; -} diff --git a/src/main/java/dev/vality/hooker/dao/WebhookAdditionalFilter.java b/src/main/java/dev/vality/hooker/dao/WebhookAdditionalFilter.java index 16c9719..54a0fd5 100644 --- a/src/main/java/dev/vality/hooker/dao/WebhookAdditionalFilter.java +++ b/src/main/java/dev/vality/hooker/dao/WebhookAdditionalFilter.java @@ -1,15 +1,8 @@ package dev.vality.hooker.dao; import dev.vality.hooker.model.EventType; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.NoArgsConstructor; -import lombok.ToString; +import lombok.*; -/** - * Created by inalarsanukaev on 18.04.17. - */ @Data @ToString @AllArgsConstructor diff --git a/src/main/java/dev/vality/hooker/dao/impl/AllHookTablesRow.java b/src/main/java/dev/vality/hooker/dao/impl/AllHookTablesRow.java index cb71085..86aef69 100644 --- a/src/main/java/dev/vality/hooker/dao/impl/AllHookTablesRow.java +++ b/src/main/java/dev/vality/hooker/dao/impl/AllHookTablesRow.java @@ -5,9 +5,6 @@ import lombok.AllArgsConstructor; import lombok.Getter; import lombok.Setter; -/** - * Created by inalarsanukaev on 18.04.17. - */ @AllArgsConstructor @Getter @Setter diff --git a/src/main/java/dev/vality/hooker/dao/impl/CustomerDaoImpl.java b/src/main/java/dev/vality/hooker/dao/impl/CustomerDaoImpl.java index e4413ab..578eb51 100644 --- a/src/main/java/dev/vality/hooker/dao/impl/CustomerDaoImpl.java +++ b/src/main/java/dev/vality/hooker/dao/impl/CustomerDaoImpl.java @@ -1,12 +1,15 @@ package dev.vality.hooker.dao.impl; import dev.vality.hooker.dao.CustomerDao; +import dev.vality.hooker.dao.rowmapper.CustomerRowMapper; import dev.vality.hooker.exception.DaoException; import dev.vality.hooker.model.CustomerMessage; import dev.vality.hooker.model.CustomerMessageEnum; -import dev.vality.hooker.model.EventType; +import dev.vality.hooker.model.WebhookMessageModel; +import dev.vality.swag_webhook_events.model.Event; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.core.NestedRuntimeException; import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.jdbc.core.RowMapper; @@ -14,88 +17,60 @@ import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.stereotype.Component; -import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Collection; import java.util.List; -/** - * Created by inalarsanukaev on 13.10.17. - */ @Slf4j @Component @RequiredArgsConstructor public class CustomerDaoImpl implements CustomerDao { - public static final String ID = "id"; - public static final String EVENT_ID = "event_id"; - public static final String TYPE = "type"; - public static final String OCCURED_AT = "occured_at"; - public static final String SEQUENCE_ID = "sequence_id"; - public static final String CHANGE_ID = "change_id"; - public static final String PARTY_ID = "party_id"; - public static final String EVENT_TYPE = "event_type"; - public static final String CUSTOMER_ID = "customer_id"; - public static final String CUSTOMER_SHOP_ID = "customer_shop_id"; - public static final String BINDING_ID = "binding_id"; - private static RowMapper messageRowMapper = (rs, i) -> { - CustomerMessage message = new CustomerMessage(); - message.setId(rs.getLong(ID)); - message.setEventId(rs.getLong(EVENT_ID)); - message.setPartyId(rs.getString(PARTY_ID)); - message.setEventTime(rs.getString(OCCURED_AT)); - message.setSequenceId(rs.getLong(SEQUENCE_ID)); - message.setChangeId(rs.getInt(CHANGE_ID)); - message.setType(CustomerMessageEnum.lookup(rs.getString(TYPE))); - message.setEventType(EventType.valueOf(rs.getString(EVENT_TYPE))); - message.setCustomerId(rs.getString(CUSTOMER_ID)); - message.setShopId(rs.getString(CUSTOMER_SHOP_ID)); - message.setBindingId(rs.getString(BINDING_ID)); - return message; - }; + private final RowMapper customerMessageRowMapper; + private final RowMapper > webhookMessageModelRowMapper; private final NamedParameterJdbcTemplate jdbcTemplate; + @Value("${parent.not.exist.id:-1}") + private Long parentNotExistId; + @Override public CustomerMessage getAny(String customerId, CustomerMessageEnum type) throws DaoException { - CustomerMessage result = null; final String sql = "SELECT * FROM hook.customer_message " + "WHERE customer_id =:customer_id AND type=CAST(:type as hook.customer_message_type) " + "ORDER BY id DESC LIMIT 1"; - MapSqlParameterSource params = - new MapSqlParameterSource(CUSTOMER_ID, customerId).addValue(TYPE, type.getValue()); + MapSqlParameterSource params = new MapSqlParameterSource() + .addValue(CustomerRowMapper.CUSTOMER_ID, customerId) + .addValue(CustomerRowMapper.TYPE, type.getValue()); try { - result = jdbcTemplate.queryForObject(sql, params, messageRowMapper); + return jdbcTemplate.queryForObject(sql, params, customerMessageRowMapper); } catch (EmptyResultDataAccessException e) { log.warn("CustomerMessage with customerId {}, type {} not exist!", customerId, type); + return null; } catch (NestedRuntimeException e) { throw new DaoException("CustomerMessageDaoImpl.getAny error with customerId " + customerId, e); } - return result; } - @Transactional - public Long create(CustomerMessage message) throws DaoException { + @Override + public Long save(CustomerMessage message) throws DaoException { final String sql = "INSERT INTO hook.customer_message " + - "(event_id, occured_at, sequence_id, change_id, type, " + + "(occured_at, sequence_id, change_id, type, " + "party_id, event_type, customer_id, customer_shop_id, binding_id) " + "VALUES " + - "(:event_id, :occured_at, :sequence_id, :change_id, CAST(:type as hook.customer_message_type), " + + "(:occured_at, :sequence_id, :change_id, CAST(:type as hook.customer_message_type), " + ":party_id, CAST(:event_type as hook.eventtype), :customer_id, :customer_shop_id, :binding_id) " + "ON CONFLICT (customer_id, sequence_id, change_id) DO NOTHING " + "RETURNING id"; MapSqlParameterSource params = new MapSqlParameterSource() - .addValue(EVENT_ID, message.getEventId()) - .addValue(OCCURED_AT, message.getEventTime()) - .addValue(SEQUENCE_ID, message.getSequenceId()) - .addValue(CHANGE_ID, message.getChangeId()) - .addValue(TYPE, message.getType().getValue()) - .addValue(PARTY_ID, message.getPartyId()) - .addValue(EVENT_TYPE, message.getEventType().name()) - .addValue(CUSTOMER_ID, message.getCustomerId()) - .addValue(CUSTOMER_SHOP_ID, message.getShopId()) - .addValue(BINDING_ID, message.getBindingId()); + .addValue(CustomerRowMapper.OCCURED_AT, message.getEventTime()) + .addValue(CustomerRowMapper.SEQUENCE_ID, message.getSequenceId()) + .addValue(CustomerRowMapper.CHANGE_ID, message.getChangeId()) + .addValue(CustomerRowMapper.TYPE, message.getType().getValue()) + .addValue(CustomerRowMapper.PARTY_ID, message.getPartyId()) + .addValue(CustomerRowMapper.EVENT_TYPE, message.getEventType().name()) + .addValue(CustomerRowMapper.CUSTOMER_ID, message.getSourceId()) + .addValue(CustomerRowMapper.CUSTOMER_SHOP_ID, message.getShopId()) + .addValue(CustomerRowMapper.BINDING_ID, message.getBindingId()); try { GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); jdbcTemplate.update(sql, params, keyHolder); @@ -106,32 +81,46 @@ public class CustomerDaoImpl implements CustomerDao { } return null; } catch (NestedRuntimeException e) { - throw new DaoException("Couldn't create customerMessage with customerId " + message.getCustomerId(), e); - } - } - - public Long getMaxEventId() { - final String sql = "select max(event_id) from hook.customer_message "; - try { - return jdbcTemplate.queryForObject(sql, new MapSqlParameterSource(), Long.class); - } catch (EmptyResultDataAccessException e) { - return null; + throw new DaoException("Couldn't create customerMessage with customerId " + message.getSourceId(), e); } } @Override - public List getBy(Collection messageIds) throws DaoException { - if (messageIds.isEmpty()) { - return new ArrayList<>(); - } - final String sql = "SELECT * FROM hook.customer_message WHERE id in (:ids)"; + public List > getWebhookModels(Long messageId) { + final String sql = "select m.*, w.id as hook_id, w.url, pk.priv_key" + + " from hook.customer_message m" + + " join hook.webhook w on m.party_id = w.party_id " + + " and w.enabled and w.topic=CAST(:message_type as hook.message_topic)" + + " join hook.webhook_to_events wte on wte.hook_id = w.id" + + " join hook.party_data pk on w.party_id=pk.party_id" + + " where m.id =:id " + + " and m.event_type = wte.event_type " + + " and (m.customer_shop_id = wte.invoice_shop_id or wte.invoice_shop_id is null) "; + MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource() + .addValue("id", messageId) + .addValue("message_type", Event.TopicEnum.CUSTOMERSTOPIC.getValue()); + return jdbcTemplate.query(sql, mapSqlParameterSource, webhookMessageModelRowMapper); + } + + @Override + public Long getParentId(Long hookId, String customerId, Long messageId) { + final String sql = "select m.id" + + " from hook.customer_message m " + + " join hook.webhook w on w.id=:hook_id" + + " join hook.webhook_to_events wte on wte.hook_id = w.id" + + " where m.customer_id =:customer_id" + + " and m.id <:id " + + " and m.event_type = wte.event_type " + + " and (m.customer_shop_id = wte.invoice_shop_id or wte.invoice_shop_id is null) " + + " order by id desc limit 1 "; + MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource() + .addValue("hook_id", hookId) + .addValue("customer_id", customerId) + .addValue("id", messageId); try { - List messagesFromDb = - jdbcTemplate.query(sql, new MapSqlParameterSource("ids", messageIds), messageRowMapper); - log.debug("messagesFromDb {}", messagesFromDb); - return messagesFromDb; - } catch (NestedRuntimeException e) { - throw new DaoException("CustomerMessageDaoImpl.getByIds error", e); + return jdbcTemplate.queryForObject(sql, mapSqlParameterSource, Long.class); + } catch (EmptyResultDataAccessException e) { + return parentNotExistId; } } -} +} \ No newline at end of file diff --git a/src/main/java/dev/vality/hooker/dao/impl/CustomerQueueDao.java b/src/main/java/dev/vality/hooker/dao/impl/CustomerQueueDao.java deleted file mode 100644 index e008503..0000000 --- a/src/main/java/dev/vality/hooker/dao/impl/CustomerQueueDao.java +++ /dev/null @@ -1,106 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import dev.vality.hooker.dao.QueueDao; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.model.CustomerQueue; -import dev.vality.hooker.model.Hook; -import dev.vality.hooker.retry.RetryPolicyType; -import dev.vality.swag_webhook_events.model.Event; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.NestedRuntimeException; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Component; - -import java.util.Collection; -import java.util.List; - -/** - * Created by inalarsanukaev on 14.11.17. - */ -@Slf4j -@Component -@RequiredArgsConstructor -public class CustomerQueueDao implements QueueDao { - - public static RowMapper queueWithPolicyRowMapper = (rs, i) -> { - CustomerQueue queue = new CustomerQueue(); - queue.setId(rs.getLong("id")); - queue.setCustomerId(rs.getString("customer_id")); - Hook hook = new Hook(); - hook.setId(rs.getLong("hook_id")); - hook.setPartyId(rs.getString("party_id")); - hook.setTopic(rs.getString("message_type")); - hook.setUrl(rs.getString("url")); - hook.setPubKey(rs.getString("pub_key")); - hook.setPrivKey(rs.getString("priv_key")); - hook.setEnabled(rs.getBoolean("enabled")); - RetryPolicyType retryPolicyType = RetryPolicyType.valueOf(rs.getString("retry_policy")); - hook.setRetryPolicyType(retryPolicyType); - queue.setHook(hook); - queue.setRetryPolicyRecord(retryPolicyType.build(rs)); - return queue; - }; - private final NamedParameterJdbcTemplate jdbcTemplate; - - public void createWithPolicy(long messageId) throws DaoException { - final String sql = "with queue as ( " + - " insert into hook.customer_queue(hook_id, customer_id)" + - " select w.id, m.customer_id" + - " from hook.customer_message m" + - " join hook.webhook w on m.party_id = w.party_id " + - " and w.enabled and w.topic=CAST(:message_type as hook.message_topic)" + - " where m.id = :id " + - " on conflict(hook_id, customer_id) do nothing returning *) " + - " insert into hook.simple_retry_policy(queue_id, message_type) " + - " select id, CAST(:message_type as hook.message_topic) from queue"; - try { - int count = jdbcTemplate.update(sql, new MapSqlParameterSource("id", messageId) - .addValue("message_type", getMessagesTopic())); - log.info("Created {} queues for messageId {}", count, messageId); - } catch (NestedRuntimeException e) { - log.error("Fail to createWithPolicy queue {}", messageId, e); - throw new DaoException(e); - } - } - - @Override - public List getWithPolicies(Collection ids) throws DaoException { - final String sql = - " select q.id, q.hook_id, q.customer_id, wh.party_id, wh.url, k.pub_key, k.priv_key, wh.enabled, " + - " wh.retry_policy, srp.fail_count, srp.last_fail_time, " + - " srp.next_fire_time_ms, srp.message_type " + - " from hook.customer_queue q " + - " join hook.webhook wh on wh.id = q.hook_id " + - " and wh.enabled and wh.topic=CAST(:message_type as hook.message_topic)" + - " join hook.party_data k on k.party_id = wh.party_id " + - " left join hook.simple_retry_policy srp on q.id = srp.queue_id " + - " and srp.message_type=CAST(:message_type as hook.message_topic)" + - " where q.id in (:ids) and q.enabled"; - final MapSqlParameterSource params = new MapSqlParameterSource("ids", ids) - .addValue("message_type", getMessagesTopic()); - - try { - return jdbcTemplate.query(sql, params, queueWithPolicyRowMapper); - } catch (NestedRuntimeException e) { - throw new DaoException(e); - } - } - - @Override - public void disable(long id) throws DaoException { - final String sql = " UPDATE hook.customer_queue SET enabled = FALSE where id=:id;"; - try { - jdbcTemplate.update(sql, new MapSqlParameterSource("id", id)); - } catch (NestedRuntimeException e) { - log.error("Fail to disable queue: {}", id, e); - throw new DaoException(e); - } - } - - public String getMessagesTopic() { - return Event.TopicEnum.CUSTOMERSTOPIC.getValue(); - } -} diff --git a/src/main/java/dev/vality/hooker/dao/impl/CustomerTaskDao.java b/src/main/java/dev/vality/hooker/dao/impl/CustomerTaskDao.java deleted file mode 100644 index 5090eb1..0000000 --- a/src/main/java/dev/vality/hooker/dao/impl/CustomerTaskDao.java +++ /dev/null @@ -1,112 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import dev.vality.hooker.dao.AbstractTaskDao; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.model.Task; -import dev.vality.swag_webhook_events.model.Event; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.NestedRuntimeException; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; - -@Slf4j -@Component -public class CustomerTaskDao extends AbstractTaskDao { - - public CustomerTaskDao(NamedParameterJdbcTemplate jdbcTemplate) { - super(jdbcTemplate); - } - - @Override - protected String getMessageTopic() { - return Event.TopicEnum.CUSTOMERSTOPIC.getValue(); - } - - public void create(long messageId) throws DaoException { - final String sql = - " insert into hook.scheduled_task(message_id, queue_id, message_type)" + - " select m.id, q.id, w.topic" + - " from hook.customer_message m" + - " join hook.webhook w on m.party_id = w.party_id " + - " and w.enabled and w.topic=CAST(:message_type as hook.message_topic)" + - " join hook.webhook_to_events wte on wte.hook_id = w.id" + - " join hook.customer_queue q on q.hook_id=w.id and q.enabled and q.customer_id=m.customer_id" + - " where m.id = :message_id " + - " and m.event_type = wte.event_type " + - " and (m.customer_shop_id = wte.invoice_shop_id or wte.invoice_shop_id is null) " + - " ON CONFLICT (message_id, queue_id, message_type) DO NOTHING"; - try { - jdbcTemplate.update(sql, new MapSqlParameterSource("message_id", messageId) - .addValue("message_type", getMessageTopic())); - } catch (NestedRuntimeException e) { - log.error("Fail to create tasks for messages.", e); - throw new DaoException(e); - } - } - - public int create(long hookId, String customerId) throws DaoException { - final String sql = - " insert into hook.scheduled_task(message_id, queue_id, message_type)" + - " select m.id, q.id, w.topic" + - " from hook.customer_message m" + - " join hook.webhook w on m.party_id = w.party_id " + - " and w.id = :hook_id " + - " and w.enabled " + - " and w.topic=CAST(:message_type as hook.message_topic)" + - " join hook.webhook_to_events wte on wte.hook_id = w.id" + - " join hook.customer_queue q on q.hook_id=w.id " + - " and q.enabled " + - " and q.customer_id=m.customer_id" + - " where m.customer_id = :customer_id " + - " and m.event_type = wte.event_type " + - " and (m.customer_shop_id = wte.invoice_shop_id or wte.invoice_shop_id is null) " + - " ON CONFLICT (message_id, queue_id, message_type) DO NOTHING"; - try { - return jdbcTemplate.update(sql, new MapSqlParameterSource("hook_id", hookId) - .addValue("customer_id", customerId) - .addValue("message_type", getMessageTopic())); - } catch (NestedRuntimeException e) { - log.error("Fail to create tasks for messages.", e); - throw new DaoException(e); - } - } - - @Override - public Map > getScheduled() throws DaoException { - final String sql = " WITH scheduled AS (" + - "SELECT st.message_id, st.queue_id, cq.customer_id " + - "FROM hook.scheduled_task st " + - "JOIN hook.customer_queue cq ON st.queue_id=cq.id AND cq.enabled " + - "JOIN hook.simple_retry_policy srp ON st.queue_id=srp.queue_id " + - "AND st.message_type=srp.message_type " + - "JOIN hook.webhook w ON cq.hook_id = w.id AND w.enabled " + - "WHERE st.message_type = CAST(:message_type as hook.message_topic) " + - "AND COALESCE(srp.next_fire_time_ms, 0) < :curr_time " + - "ORDER BY w.availability ASC, st.message_id ASC " + - "LIMIT 1 " + - "FOR UPDATE OF cq SKIP LOCKED " + - "), locked_customer_queue AS (" + - " SELECT ciq.id FROM hook.customer_queue ciq " + - " WHERE ciq.customer_id IN (SELECT DISTINCT schd.customer_id FROM scheduled schd) " + - " FOR UPDATE OF ciq SKIP LOCKED " + - ") SELECT message_id, queue_id FROM hook.scheduled_task s " + - " JOIN locked_customer_queue lq ON s.queue_id = lq.id " + - " ORDER BY s.message_id" + - " FOR UPDATE OF s SKIP LOCKED"; - try { - List tasks = jdbcTemplate.query(sql, - new MapSqlParameterSource("message_type", getMessageTopic()) - .addValue("curr_time", System.currentTimeMillis()), - taskRowMapper); - return splitByQueue(tasks); - } catch (NestedRuntimeException e) { - log.warn("Fail to get active tasks from scheduled_task", e); - throw new DaoException(e); - } - } - -} diff --git a/src/main/java/dev/vality/hooker/dao/impl/EventIdsGeneratorDaoImpl.java b/src/main/java/dev/vality/hooker/dao/impl/EventIdsGeneratorDaoImpl.java deleted file mode 100644 index a6ccaff..0000000 --- a/src/main/java/dev/vality/hooker/dao/impl/EventIdsGeneratorDaoImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import dev.vality.hooker.dao.IdsGeneratorDao; -import dev.vality.hooker.exception.DaoException; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.NestedRuntimeException; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Slf4j -@Component -@RequiredArgsConstructor -public class EventIdsGeneratorDaoImpl implements IdsGeneratorDao { - - private final NamedParameterJdbcTemplate jdbcTemplate; - - @Override - public List get(int size) throws DaoException { - try { - String sql = "select nextval('hook.event_id_seq') from generate_series(1, :size)"; - MapSqlParameterSource parameterSource = new MapSqlParameterSource().addValue("size", size); - return jdbcTemplate.queryForList(sql, parameterSource, Long.class); - } catch (NestedRuntimeException e) { - throw new DaoException(e); - } - } -} diff --git a/src/main/java/dev/vality/hooker/dao/impl/HookDaoImpl.java b/src/main/java/dev/vality/hooker/dao/impl/HookDaoImpl.java index 06e468f..9e657fd 100644 --- a/src/main/java/dev/vality/hooker/dao/impl/HookDaoImpl.java +++ b/src/main/java/dev/vality/hooker/dao/impl/HookDaoImpl.java @@ -21,16 +21,9 @@ import org.springframework.jdbc.support.KeyHolder; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; -/** - * Created by inal on 28.11.2016. - */ @Slf4j @Component @RequiredArgsConstructor diff --git a/src/main/java/dev/vality/hooker/dao/impl/InvoicingDaoImpl.java b/src/main/java/dev/vality/hooker/dao/impl/InvoicingDaoImpl.java new file mode 100644 index 0000000..9f8297d --- /dev/null +++ b/src/main/java/dev/vality/hooker/dao/impl/InvoicingDaoImpl.java @@ -0,0 +1,137 @@ +package dev.vality.hooker.dao.impl; + +import dev.vality.hooker.dao.InvoicingMessageDao; +import dev.vality.hooker.dao.rowmapper.InvoicingRowMapper; +import dev.vality.hooker.exception.DaoException; +import dev.vality.hooker.exception.NotFoundException; +import dev.vality.hooker.model.InvoicingMessage; +import dev.vality.hooker.model.InvoicingMessageKey; +import dev.vality.hooker.model.WebhookMessageModel; +import dev.vality.swag_webhook_events.model.Event; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.NestedRuntimeException; +import org.springframework.dao.EmptyResultDataAccessException; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Slf4j +@Component +@RequiredArgsConstructor +public class InvoicingDaoImpl implements InvoicingMessageDao { + + private final RowMapper invoicingMessageRowMapper; + private final RowMapper > webhookMessageModelRowMapper; + private final NamedParameterJdbcTemplate jdbcTemplate; + + @Value("${parent.not.exist.id:-1}") + private Long parentNotExistId; + + @Override + public Long save(InvoicingMessage message) { + try { + final String sql = "INSERT INTO hook.message" + + "(event_time, sequence_id, change_id, type, party_id, event_type, " + + "invoice_id, shop_id, invoice_status, payment_id, payment_status, refund_id, refund_status) " + + "VALUES " + + "(:event_time, :sequence_id, :change_id, :type, :party_id, " + + "CAST(:event_type as hook.eventtype), :invoice_id, :shop_id, :invoice_status, :payment_id, " + + ":payment_status, :refund_id, :refund_status) " + + "ON CONFLICT (invoice_id, sequence_id, change_id) DO NOTHING " + + "RETURNING id"; + + MapSqlParameterSource sqlParameterSources = new MapSqlParameterSource() + .addValue(InvoicingRowMapper.EVENT_TIME, message.getEventTime()) + .addValue(InvoicingRowMapper.SEQUENCE_ID, message.getSequenceId()) + .addValue(InvoicingRowMapper.CHANGE_ID, message.getChangeId()) + .addValue(InvoicingRowMapper.TYPE, message.getType().getValue()) + .addValue(InvoicingRowMapper.PARTY_ID, message.getPartyId()) + .addValue(InvoicingRowMapper.EVENT_TYPE, message.getEventType().toString()) + .addValue(InvoicingRowMapper.INVOICE_ID, message.getSourceId()) + .addValue(InvoicingRowMapper.SHOP_ID, message.getShopId()) + .addValue(InvoicingRowMapper.INVOICE_STATUS, message.getInvoiceStatus().getValue()) + .addValue(InvoicingRowMapper.PAYMENT_ID, message.getPaymentId()) + .addValue(InvoicingRowMapper.PAYMENT_STATUS, + message.getPaymentStatus() != null ? message.getPaymentStatus().getValue() : null) + .addValue(InvoicingRowMapper.REFUND_ID, message.getRefundId()) + .addValue(InvoicingRowMapper.REFUND_STATUS, + message.getRefundStatus() != null ? message.getRefundStatus().getValue() : null); + GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); + jdbcTemplate.update(sql, sqlParameterSources, keyHolder); + return keyHolder.getKey() == null ? null : keyHolder.getKey().longValue(); + } catch (NestedRuntimeException e) { + throw new DaoException("Couldn't save batch messages: " + message.getSourceId(), e); + } + } + + @Override + public InvoicingMessage getInvoicingMessage(InvoicingMessageKey key) throws NotFoundException, DaoException { + final String sql = "SELECT * FROM hook.message WHERE invoice_id =:invoice_id" + + " AND (payment_id IS NULL OR payment_id=:payment_id)" + + " AND (refund_id IS NULL OR refund_id=:refund_id)" + + " AND type =:type ORDER BY id DESC LIMIT 1"; + var params = new MapSqlParameterSource(InvoicingRowMapper.INVOICE_ID, key.getInvoiceId()) + .addValue(InvoicingRowMapper.PAYMENT_ID, key.getPaymentId()) + .addValue(InvoicingRowMapper.REFUND_ID, key.getRefundId()) + .addValue(InvoicingRowMapper.TYPE, key.getType().getValue()); + try { + return jdbcTemplate.queryForObject(sql, params, invoicingMessageRowMapper); + } catch (EmptyResultDataAccessException e) { + throw new NotFoundException(String.format("InvoicingMessage not found %s!", key)); + } catch (NestedRuntimeException e) { + throw new DaoException(String.format("InvoicingMessage error %s", key), e); + } + } + + @Override + public List > getWebhookModels(Long messageId) { + final String sql = "select m.*, w.id as hook_id, w.url, pk.priv_key" + + " from hook.message m" + + " join hook.webhook w on m.party_id = w.party_id " + + " and w.enabled and w.topic=CAST(:message_type as hook.message_topic)" + + " join hook.webhook_to_events wte on wte.hook_id = w.id" + + " join hook.party_data pk on w.party_id=pk.party_id" + + " where m.id =:id " + + " and m.event_type = wte.event_type " + + " and (m.shop_id = wte.invoice_shop_id or wte.invoice_shop_id is null) " + + " and (m.invoice_status = wte.invoice_status or wte.invoice_status is null) " + + " and (m.payment_status = wte.invoice_payment_status or wte.invoice_payment_status is null)" + + " and (m.refund_status = wte.invoice_payment_refund_status " + + " or wte.invoice_payment_refund_status is null)"; + MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource().addValue("id", messageId) + .addValue("message_type", Event.TopicEnum.INVOICESTOPIC.getValue()); + return jdbcTemplate.query(sql, mapSqlParameterSource, webhookMessageModelRowMapper); + } + + @Override + public Long getParentId(Long hookId, String invoiceId, Long messageId) { + final String sql = "select m.id" + + " from hook.message m " + + " join hook.webhook w on w.id=:hook_id" + + " join hook.webhook_to_events wte on wte.hook_id = w.id" + + " where m.invoice_id =:invoice_id" + + " and m.id <:id " + + " and m.event_type = wte.event_type " + + " and (m.shop_id = wte.invoice_shop_id or wte.invoice_shop_id is null) " + + " and (m.invoice_status = wte.invoice_status or wte.invoice_status is null) " + + " and (m.payment_status = wte.invoice_payment_status or wte.invoice_payment_status is null)" + + " and (m.refund_status = wte.invoice_payment_refund_status " + + " or wte.invoice_payment_refund_status is null)" + + " order by id desc limit 1 "; + MapSqlParameterSource mapSqlParameterSource = new MapSqlParameterSource() + .addValue("hook_id", hookId) + .addValue("invoice_id", invoiceId) + .addValue("id", messageId); + try { + return jdbcTemplate.queryForObject(sql, mapSqlParameterSource, Long.class); + } catch (EmptyResultDataAccessException e) { + return parentNotExistId; + } + } +} diff --git a/src/main/java/dev/vality/hooker/dao/impl/InvoicingMessageDaoImpl.java b/src/main/java/dev/vality/hooker/dao/impl/InvoicingMessageDaoImpl.java deleted file mode 100644 index d2eb26b..0000000 --- a/src/main/java/dev/vality/hooker/dao/impl/InvoicingMessageDaoImpl.java +++ /dev/null @@ -1,132 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import com.github.benmanes.caffeine.cache.Cache; -import dev.vality.hooker.dao.InvoicingMessageDao; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.exception.NotFoundException; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.utils.KeyUtils; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.NestedRuntimeException; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Component; - -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.CHANGE_ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.EVENT_TIME; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.EVENT_TYPE; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.INVOICE_ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.INVOICE_STATUS; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.NEW_EVENT_ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.PARTY_ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.PAYMENT_ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.PAYMENT_STATUS; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.REFUND_ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.REFUND_STATUS; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.SEQUENCE_ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.SHOP_ID; -import static dev.vality.hooker.dao.impl.InvoicingMessageRowMapper.TYPE; - -@Slf4j -@Component -@RequiredArgsConstructor -public class InvoicingMessageDaoImpl implements InvoicingMessageDao { - - private static RowMapper messageRowMapper = new InvoicingMessageRowMapper(); - private final NamedParameterJdbcTemplate jdbcTemplate; - private final Cache invoicingCache; - - public void saveBatch(List messages) throws DaoException { - int[] batchMessagesResult = saveBatchMessages(messages); - log.info("Batch messages saved info {}", - IntStream.range(0, messages.size()) - .mapToObj(i -> "(" + i + " : " + batchMessagesResult[i] + " : " + messages.get(i).getId() + - " : " + messages.get(i).getInvoiceId() + ")") - .collect(Collectors.toList())); - } - - private int[] saveBatchMessages(List messages) { - try { - messages.forEach(m -> invoicingCache.put(KeyUtils.key(m), m)); - - final String sql = "INSERT INTO hook.message" + - "(id, new_event_id, event_time, sequence_id, change_id, type, party_id, event_type, " + - "invoice_id, shop_id, invoice_status, payment_id, payment_status, refund_id, refund_status) " + - "VALUES " + - "(:id, :new_event_id, :event_time, :sequence_id, :change_id, :type, :party_id, " + - "CAST(:event_type as hook.eventtype), :invoice_id, :shop_id, :invoice_status, :payment_id, " + - ":payment_status, :refund_id, :refund_status) " + - "ON CONFLICT (invoice_id, sequence_id, change_id) DO NOTHING "; - - MapSqlParameterSource[] sqlParameterSources = messages.stream() - .map(message -> new MapSqlParameterSource() - .addValue(ID, message.getId()) - .addValue(NEW_EVENT_ID, message.getEventId()) - .addValue(EVENT_TIME, message.getEventTime()) - .addValue(SEQUENCE_ID, message.getSequenceId()) - .addValue(CHANGE_ID, message.getChangeId()) - .addValue(TYPE, message.getType().getValue()) - .addValue(PARTY_ID, message.getPartyId()) - .addValue(EVENT_TYPE, message.getEventType().toString()) - .addValue(INVOICE_ID, message.getInvoiceId()) - .addValue(SHOP_ID, message.getShopId()) - .addValue(INVOICE_STATUS, message.getInvoiceStatus().getValue()) - .addValue(PAYMENT_ID, message.getPaymentId()) - .addValue(PAYMENT_STATUS, - message.getPaymentStatus() != null ? message.getPaymentStatus().getValue() : null) - .addValue(REFUND_ID, message.getRefundId()) - .addValue(REFUND_STATUS, - message.getRefundStatus() != null ? message.getRefundStatus().getValue() : null)) - .toArray(MapSqlParameterSource[]::new); - return jdbcTemplate.batchUpdate(sql, sqlParameterSources); - } catch (NestedRuntimeException e) { - List shortInfo = messages.stream() - .map(m -> "(" + m.getId() + " : " + m.getInvoiceId() + ")") - .collect(Collectors.toList()); - throw new DaoException("Couldn't save batch messages: " + shortInfo, e); - } - } - - @Override - public InvoicingMessage getInvoicingMessage(InvoicingMessageKey key) throws NotFoundException, DaoException { - InvoicingMessage result = invoicingCache.getIfPresent(key); - if (result != null) { - return result; - } - final String sql = "SELECT * FROM hook.message WHERE invoice_id =:invoice_id" + - " AND (payment_id IS NULL OR payment_id=:payment_id)" + - " AND (refund_id IS NULL OR refund_id=:refund_id)" + - " AND type =:type ORDER BY id DESC LIMIT 1"; - MapSqlParameterSource params = new MapSqlParameterSource(INVOICE_ID, key.getInvoiceId()) - .addValue(PAYMENT_ID, key.getPaymentId()) - .addValue(REFUND_ID, key.getRefundId()) - .addValue(TYPE, key.getType().getValue()); - try { - return jdbcTemplate.queryForObject(sql, params, messageRowMapper); - } catch (EmptyResultDataAccessException e) { - throw new NotFoundException(String.format("InvoicingMessage not found %s!", key.toString())); - } catch (NestedRuntimeException e) { - throw new DaoException(String.format("InvoicingMessage error %s", key.toString()), e); - } - } - - @Override - public List getBy(Collection messageIds) throws DaoException { - final String sql = "SELECT * FROM hook.message WHERE id in (:ids)"; - try { - return jdbcTemplate.query(sql, new MapSqlParameterSource("ids", messageIds), messageRowMapper); - } catch (NestedRuntimeException e) { - throw new DaoException("Couldn't get invoice message by ids: " + messageIds, e); - } - } -} diff --git a/src/main/java/dev/vality/hooker/dao/impl/InvoicingQueueDao.java b/src/main/java/dev/vality/hooker/dao/impl/InvoicingQueueDao.java deleted file mode 100644 index b145d7c..0000000 --- a/src/main/java/dev/vality/hooker/dao/impl/InvoicingQueueDao.java +++ /dev/null @@ -1,105 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import dev.vality.hooker.dao.QueueDao; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.model.Hook; -import dev.vality.hooker.model.InvoicingQueue; -import dev.vality.hooker.retry.RetryPolicyType; -import dev.vality.swag_webhook_events.model.Event; -import lombok.RequiredArgsConstructor; -import org.springframework.core.NestedRuntimeException; -import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Component; - -import java.util.Collection; -import java.util.List; - -/** - * Created by inalarsanukaev on 14.11.17. - */ -@Component -@RequiredArgsConstructor -public class InvoicingQueueDao implements QueueDao { - - public static RowMapper queueWithPolicyRowMapper = (rs, i) -> { - InvoicingQueue queue = new InvoicingQueue(); - queue.setId(rs.getLong("id")); - queue.setInvoiceId(rs.getString("invoice_id")); - Hook hook = new Hook(); - hook.setId(rs.getLong("hook_id")); - hook.setPartyId(rs.getString("party_id")); - hook.setTopic(rs.getString("message_type")); - hook.setUrl(rs.getString("url")); - hook.setPubKey(rs.getString("pub_key")); - hook.setPrivKey(rs.getString("priv_key")); - hook.setEnabled(rs.getBoolean("enabled")); - RetryPolicyType retryPolicyType = RetryPolicyType.valueOf(rs.getString("retry_policy")); - hook.setRetryPolicyType(retryPolicyType); - queue.setHook(hook); - queue.setRetryPolicyRecord(retryPolicyType.build(rs)); - return queue; - }; - private final NamedParameterJdbcTemplate jdbcTemplate; - - public int[] saveBatchWithPolicies(List messageIds) throws DaoException { - final String sql = "with queue as ( " + - " insert into hook.invoicing_queue(hook_id, invoice_id)" + - " select w.id , m.invoice_id" + - " from hook.message m" + - " join hook.webhook w on m.party_id = w.party_id " + - " and w.enabled and w.topic=CAST(:message_type as hook.message_topic)" + - " where m.id = :id " + - " on conflict(hook_id, invoice_id) do nothing returning *) " + - " insert into hook.simple_retry_policy(queue_id, message_type) " + - " select id, CAST(:message_type as hook.message_topic) from queue"; - MapSqlParameterSource[] sqlParameterSources = messageIds - .stream() - .map(id -> new MapSqlParameterSource() - .addValue("id", id) - .addValue("message_type", Event.TopicEnum.INVOICESTOPIC.getValue())) - .toArray(MapSqlParameterSource[]::new); - try { - return jdbcTemplate.batchUpdate(sql, sqlParameterSources); - } catch (NestedRuntimeException e) { - throw new DaoException("Couldn't save queue batch with messageIds=" + messageIds, e); - } - } - - @Override - public List getWithPolicies(Collection ids) { - final String sql = - " select q.id, q.hook_id, q.invoice_id, wh.party_id, wh.url, k.pub_key, k.priv_key, wh.enabled, " + - " wh.retry_policy, srp.fail_count, srp.last_fail_time, " + - " srp.next_fire_time_ms, srp.message_type " + - " from hook.invoicing_queue q " + - " join hook.webhook wh on wh.id = q.hook_id " + - " and wh.enabled and wh.topic=CAST(:message_type as hook.message_topic)" + - " join hook.party_data k on k.party_id = wh.party_id " + - " left join hook.simple_retry_policy srp on q.id = srp.queue_id " + - " and srp.message_type=CAST(:message_type as hook.message_topic)" + - " where q.id in (:ids) and q.enabled"; - final MapSqlParameterSource params = new MapSqlParameterSource("ids", ids) - .addValue("message_type", getMessagesTopic()); - try { - return jdbcTemplate.query(sql, params, queueWithPolicyRowMapper); - } catch (NestedRuntimeException e) { - throw new DaoException("Couldn't get queue by queueIds=" + ids, e); - } - } - - @Override - public void disable(long id) throws DaoException { - final String sql = " UPDATE hook.invoicing_queue SET enabled = FALSE where id=:id;"; - try { - jdbcTemplate.update(sql, new MapSqlParameterSource("id", id)); - } catch (NestedRuntimeException e) { - throw new DaoException("Couldn't disable queue with id=" + id, e); - } - } - - public String getMessagesTopic() { - return Event.TopicEnum.INVOICESTOPIC.getValue(); - } -} diff --git a/src/main/java/dev/vality/hooker/dao/impl/InvoicingTaskDao.java b/src/main/java/dev/vality/hooker/dao/impl/InvoicingTaskDao.java deleted file mode 100644 index 659a989..0000000 --- a/src/main/java/dev/vality/hooker/dao/impl/InvoicingTaskDao.java +++ /dev/null @@ -1,130 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import dev.vality.hooker.dao.AbstractTaskDao; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.model.Task; -import dev.vality.swag_webhook_events.model.Event; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.NestedRuntimeException; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Component; - -import java.util.List; -import java.util.Map; - -/** - * Created by jeckep on 17.04.17. - */ -@Slf4j -@Component -public class InvoicingTaskDao extends AbstractTaskDao { - - public InvoicingTaskDao(NamedParameterJdbcTemplate jdbcTemplate) { - super(jdbcTemplate); - } - - @Override - protected String getMessageTopic() { - return Event.TopicEnum.INVOICESTOPIC.getValue(); - } - - //TODO limit invoices from hook - public int save(List messageIds) throws DaoException { - if (messageIds == null || messageIds.isEmpty()) { - return 0; - } - final String sql = - " insert into hook.scheduled_task(message_id, queue_id, message_type)" + - " select m.id, q.id, w.topic" + - " from hook.message m" + - " join hook.webhook w on m.party_id = w.party_id " + - " and w.enabled and w.topic=CAST(:message_type as hook.message_topic)" + - " join hook.webhook_to_events wte on wte.hook_id = w.id" + - " join hook.invoicing_queue q on q.hook_id=w.id and q.enabled and q.invoice_id=m.invoice_id" + - " where m.id in (:message_ids) " + - " and m.event_type = wte.event_type " + - " and (m.shop_id = wte.invoice_shop_id or wte.invoice_shop_id is null) " + - " and (m.invoice_status = wte.invoice_status or wte.invoice_status is null) " + - " and (m.payment_status = wte.invoice_payment_status or wte.invoice_payment_status is null)" + - " and (m.refund_status = wte.invoice_payment_refund_status " + - " or wte.invoice_payment_refund_status is null)" + - " ON CONFLICT (message_id, queue_id, message_type) DO NOTHING"; - - final MapSqlParameterSource sqlParameterSources = new MapSqlParameterSource("message_ids", messageIds) - .addValue("message_type", Event.TopicEnum.INVOICESTOPIC.getValue()); - - try { - return jdbcTemplate.update(sql, sqlParameterSources); - } catch (NestedRuntimeException e) { - throw new DaoException("Failed to create tasks for messageIds=" + messageIds, e); - } - } - - public int save(Long hookId, String invoiceId) throws DaoException { - final String sql = - " insert into hook.scheduled_task(message_id, queue_id, message_type)" + - " select m.id, q.id, w.topic" + - " from hook.message m" + - " join hook.webhook w on m.party_id = w.party_id " + - " and w.id = :hook_id " + - " and w.enabled " + - " and w.topic=CAST(:message_type as hook.message_topic)" + - " join hook.webhook_to_events wte on wte.hook_id = w.id" + - " join hook.invoicing_queue q on q.hook_id=w.id " + - " and q.enabled " + - " and q.invoice_id=m.invoice_id" + - " where m.invoice_id = :invoice_id " + - " and m.event_type = wte.event_type " + - " and (m.shop_id = wte.invoice_shop_id or wte.invoice_shop_id is null) " + - " and (m.invoice_status = wte.invoice_status or wte.invoice_status is null) " + - " and (m.payment_status = wte.invoice_payment_status or wte.invoice_payment_status is null)" + - " and (m.refund_status = wte.invoice_payment_refund_status " + - " or wte.invoice_payment_refund_status is null)" + - " ON CONFLICT (message_id, queue_id, message_type) DO NOTHING"; - - final MapSqlParameterSource sqlParameterSources = new MapSqlParameterSource("hook_id", hookId) - .addValue("invoice_id", invoiceId) - .addValue("message_type", Event.TopicEnum.INVOICESTOPIC.getValue()); - - try { - return jdbcTemplate.update(sql, sqlParameterSources); - } catch (NestedRuntimeException e) { - throw new DaoException("Failed to create tasks for hook_id=" + hookId, e); - } - } - - @Override - public Map > getScheduled() throws DaoException { - final String sql = " WITH scheduled AS (" + - "SELECT st.message_id, st.queue_id, iq.invoice_id " + - "FROM hook.scheduled_task st " + - "JOIN hook.invoicing_queue iq ON st.queue_id=iq.id AND iq.enabled " + - "JOIN hook.simple_retry_policy srp ON st.queue_id=srp.queue_id " + - "AND st.message_type=srp.message_type " + - "JOIN hook.webhook w ON iq.hook_id = w.id AND w.enabled " + - "WHERE st.message_type = CAST(:message_type as hook.message_topic) " + - "AND COALESCE(srp.next_fire_time_ms, 0) < :curr_time " + - "ORDER BY w.availability ASC, st.message_id ASC " + - "LIMIT 1 " + - "FOR UPDATE OF iq SKIP LOCKED " + - "), locked_invoicing_queue AS (" + - " SELECT liq.id FROM hook.invoicing_queue liq " + - " WHERE liq.invoice_id IN (SELECT DISTINCT schd.invoice_id FROM scheduled schd) " + - " FOR UPDATE OF liq SKIP LOCKED " + - ") SELECT message_id, queue_id FROM hook.scheduled_task s " + - " JOIN locked_invoicing_queue lq ON s.queue_id = lq.id " + - " ORDER BY s.message_id " + - " FOR UPDATE OF s SKIP LOCKED"; - try { - List tasks = jdbcTemplate.query(sql, - new MapSqlParameterSource("message_type", getMessageTopic()) - .addValue("curr_time", System.currentTimeMillis()), - taskRowMapper); - return splitByQueue(tasks); - } catch (NestedRuntimeException e) { - log.warn("Fail to get active tasks from scheduled_task", e); - throw new DaoException(e); - } - } -} diff --git a/src/main/java/dev/vality/hooker/dao/impl/MessageIdsGeneratorDaoImpl.java b/src/main/java/dev/vality/hooker/dao/impl/MessageIdsGeneratorDaoImpl.java deleted file mode 100644 index c084ccc..0000000 --- a/src/main/java/dev/vality/hooker/dao/impl/MessageIdsGeneratorDaoImpl.java +++ /dev/null @@ -1,31 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import dev.vality.hooker.dao.IdsGeneratorDao; -import dev.vality.hooker.exception.DaoException; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.core.NestedRuntimeException; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Component; - -import java.util.List; - -@Slf4j -@Component -@RequiredArgsConstructor -public class MessageIdsGeneratorDaoImpl implements IdsGeneratorDao { - - private final NamedParameterJdbcTemplate jdbcTemplate; - - @Override - public List get(int size) throws DaoException { - try { - String sql = "select nextval('hook.seq') from generate_series(1, :size)"; - MapSqlParameterSource parameterSource = new MapSqlParameterSource().addValue("size", size); - return jdbcTemplate.queryForList(sql, parameterSource, Long.class); - } catch (NestedRuntimeException e) { - throw new DaoException(e); - } - } -} diff --git a/src/main/java/dev/vality/hooker/dao/impl/SimpleRetryPolicyDaoImpl.java b/src/main/java/dev/vality/hooker/dao/impl/SimpleRetryPolicyDaoImpl.java deleted file mode 100644 index 151c099..0000000 --- a/src/main/java/dev/vality/hooker/dao/impl/SimpleRetryPolicyDaoImpl.java +++ /dev/null @@ -1,35 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import dev.vality.hooker.dao.SimpleRetryPolicyDao; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.retry.impl.simple.SimpleRetryPolicyRecord; -import lombok.RequiredArgsConstructor; -import org.springframework.core.NestedRuntimeException; -import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.stereotype.Component; - -@Component -@RequiredArgsConstructor -public class SimpleRetryPolicyDaoImpl implements SimpleRetryPolicyDao { - - private final NamedParameterJdbcTemplate jdbcTemplate; - - @Override - public void update(SimpleRetryPolicyRecord record) throws DaoException { - final String sql = "update hook.simple_retry_policy " + - " set last_fail_time = :last_fail_time, " + - " fail_count = :fail_count, " + - " next_fire_time_ms = :next_fire_time_ms" + - " where queue_id = :queue_id and message_type=CAST(:message_type as hook.message_topic)"; - try { - jdbcTemplate.update(sql, new MapSqlParameterSource("queue_id", record.getQueueId()) - .addValue("message_type", record.getMessageType()) - .addValue("last_fail_time", record.getLastFailTime()) - .addValue("fail_count", record.getFailCount()) - .addValue("next_fire_time_ms", record.getNextFireTime())); - } catch (NestedRuntimeException e) { - throw new DaoException("Fail to update simple_retry_policy for record=" + record.getQueueId(), e); - } - } -} diff --git a/src/main/java/dev/vality/hooker/dao/rowmapper/CustomerRowMapper.java b/src/main/java/dev/vality/hooker/dao/rowmapper/CustomerRowMapper.java new file mode 100644 index 0000000..8b9d632 --- /dev/null +++ b/src/main/java/dev/vality/hooker/dao/rowmapper/CustomerRowMapper.java @@ -0,0 +1,40 @@ +package dev.vality.hooker.dao.rowmapper; + +import dev.vality.hooker.model.CustomerMessage; +import dev.vality.hooker.model.CustomerMessageEnum; +import dev.vality.hooker.model.EventType; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@Component +public class CustomerRowMapper implements RowMapper { + public static final String ID = "id"; + public static final String TYPE = "type"; + public static final String OCCURED_AT = "occured_at"; + public static final String SEQUENCE_ID = "sequence_id"; + public static final String CHANGE_ID = "change_id"; + public static final String PARTY_ID = "party_id"; + public static final String EVENT_TYPE = "event_type"; + public static final String CUSTOMER_ID = "customer_id"; + public static final String CUSTOMER_SHOP_ID = "customer_shop_id"; + public static final String BINDING_ID = "binding_id"; + + @Override + public CustomerMessage mapRow(ResultSet rs, int rowNum) throws SQLException { + CustomerMessage message = new CustomerMessage(); + message.setId(rs.getLong(ID)); + message.setPartyId(rs.getString(PARTY_ID)); + message.setEventTime(rs.getString(OCCURED_AT)); + message.setSequenceId(rs.getLong(SEQUENCE_ID)); + message.setChangeId(rs.getInt(CHANGE_ID)); + message.setType(CustomerMessageEnum.lookup(rs.getString(TYPE))); + message.setEventType(EventType.valueOf(rs.getString(EVENT_TYPE))); + message.setSourceId(rs.getString(CUSTOMER_ID)); + message.setShopId(rs.getString(CUSTOMER_SHOP_ID)); + message.setBindingId(rs.getString(BINDING_ID)); + return message; + } +} diff --git a/src/main/java/dev/vality/hooker/dao/impl/InvoicingMessageRowMapper.java b/src/main/java/dev/vality/hooker/dao/rowmapper/InvoicingRowMapper.java similarity index 77% rename from src/main/java/dev/vality/hooker/dao/impl/InvoicingMessageRowMapper.java rename to src/main/java/dev/vality/hooker/dao/rowmapper/InvoicingRowMapper.java index e3c3679..17de3a6 100644 --- a/src/main/java/dev/vality/hooker/dao/impl/InvoicingMessageRowMapper.java +++ b/src/main/java/dev/vality/hooker/dao/rowmapper/InvoicingRowMapper.java @@ -1,20 +1,16 @@ -package dev.vality.hooker.dao.impl; +package dev.vality.hooker.dao.rowmapper; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoiceStatusEnum; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.PaymentStatusEnum; -import dev.vality.hooker.model.RefundStatusEnum; +import dev.vality.hooker.model.*; import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Component; import java.sql.ResultSet; import java.sql.SQLException; -public class InvoicingMessageRowMapper implements RowMapper { +@Component +public class InvoicingRowMapper implements RowMapper { public static final String ID = "id"; - public static final String NEW_EVENT_ID = "new_event_id"; public static final String EVENT_TIME = "event_time"; public static final String SEQUENCE_ID = "sequence_id"; public static final String CHANGE_ID = "change_id"; @@ -33,7 +29,6 @@ public class InvoicingMessageRowMapper implements RowMapper { public InvoicingMessage mapRow(ResultSet rs, int i) throws SQLException { InvoicingMessage message = new InvoicingMessage(); message.setId(rs.getLong(ID)); - message.setEventId(rs.getLong(NEW_EVENT_ID)); message.setEventTime(rs.getString(EVENT_TIME)); message.setSequenceId(rs.getLong(SEQUENCE_ID)); message.setChangeId(rs.getInt(CHANGE_ID)); @@ -41,7 +36,7 @@ public class InvoicingMessageRowMapper implements RowMapper { message.setPartyId(rs.getString(PARTY_ID)); message.setShopId(rs.getString(SHOP_ID)); message.setEventType(EventType.valueOf(rs.getString(EVENT_TYPE))); - message.setInvoiceId(rs.getString(INVOICE_ID)); + message.setSourceId(rs.getString(INVOICE_ID)); message.setInvoiceStatus(InvoiceStatusEnum.lookup(rs.getString(INVOICE_STATUS))); message.setPaymentId(rs.getString(PAYMENT_ID)); message.setPaymentStatus(rs.getString(PAYMENT_STATUS) != null diff --git a/src/main/java/dev/vality/hooker/dao/rowmapper/WebhookModelRowMapper.java b/src/main/java/dev/vality/hooker/dao/rowmapper/WebhookModelRowMapper.java new file mode 100644 index 0000000..c8c935e --- /dev/null +++ b/src/main/java/dev/vality/hooker/dao/rowmapper/WebhookModelRowMapper.java @@ -0,0 +1,29 @@ +package dev.vality.hooker.dao.rowmapper; + +import dev.vality.hooker.model.Message; +import dev.vality.hooker.model.WebhookMessageModel; +import lombok.RequiredArgsConstructor; +import org.springframework.jdbc.core.RowMapper; + +import java.sql.ResultSet; +import java.sql.SQLException; + +@RequiredArgsConstructor +public class WebhookModelRowMapper implements RowMapper > { + + public static final String HOOK_ID = "hook_id"; + public static final String URL = "url"; + public static final String PRIV_KEY = "priv_key"; + private final RowMapper messageRowMapper; + + @Override + public WebhookMessageModel mapRow(ResultSet rs, int rowNum) throws SQLException { + T invoicingMessage = messageRowMapper.mapRow(rs, rowNum); + WebhookMessageModel webhookMessageModel = new WebhookMessageModel<>(); + webhookMessageModel.setMessage(invoicingMessage); + webhookMessageModel.setHookId(rs.getLong(HOOK_ID)); + webhookMessageModel.setUrl(rs.getString(URL)); + webhookMessageModel.setPrivateKey(rs.getString(PRIV_KEY)); + return webhookMessageModel; + } +} diff --git a/src/main/java/dev/vality/hooker/endpoint/WebhookManagerServlet.java b/src/main/java/dev/vality/hooker/endpoint/WebhookManagerServlet.java index defde30..36a0488 100644 --- a/src/main/java/dev/vality/hooker/endpoint/WebhookManagerServlet.java +++ b/src/main/java/dev/vality/hooker/endpoint/WebhookManagerServlet.java @@ -8,14 +8,8 @@ import dev.vality.woody.thrift.impl.http.event.ServiceEventLogListener; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import javax.servlet.GenericServlet; -import javax.servlet.Servlet; -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; +import javax.servlet.*; import javax.servlet.annotation.WebServlet; - import java.io.IOException; @WebServlet("/hook") diff --git a/src/main/java/dev/vality/hooker/endpoint/WebhookMessageServiceServlet.java b/src/main/java/dev/vality/hooker/endpoint/WebhookMessageServiceServlet.java deleted file mode 100644 index f92d1e2..0000000 --- a/src/main/java/dev/vality/hooker/endpoint/WebhookMessageServiceServlet.java +++ /dev/null @@ -1,48 +0,0 @@ -package dev.vality.hooker.endpoint; - -import dev.vality.damsel.webhooker.WebhookMessageServiceSrv; -import dev.vality.woody.api.event.CompositeServiceEventListener; -import dev.vality.woody.thrift.impl.http.THServiceBuilder; -import dev.vality.woody.thrift.impl.http.event.HttpServiceEventLogListener; -import dev.vality.woody.thrift.impl.http.event.ServiceEventLogListener; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; - -import javax.servlet.GenericServlet; -import javax.servlet.Servlet; -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.annotation.WebServlet; - -import java.io.IOException; - -@WebServlet("/message") -@Slf4j -@RequiredArgsConstructor -public class WebhookMessageServiceServlet extends GenericServlet { - - private final WebhookMessageServiceSrv.Iface requestHandler; - private Servlet thriftServlet; - - @Override - public void init(ServletConfig config) throws ServletException { - log.info("Hooker servlet init."); - super.init(config); - thriftServlet = new THServiceBuilder() - .withEventListener( - new CompositeServiceEventListener<>( - new ServiceEventLogListener(), - new HttpServiceEventLogListener() - ) - ) - .build(WebhookMessageServiceSrv.Iface.class, requestHandler); - } - - @Override - public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { - log.info("Start new request to WebhookMessageServiceServlet."); - thriftServlet.service(req, res); - } -} diff --git a/src/main/java/dev/vality/hooker/exception/RemoteHostException.java b/src/main/java/dev/vality/hooker/exception/RemoteHostException.java index 38307f5..b02dc4f 100644 --- a/src/main/java/dev/vality/hooker/exception/RemoteHostException.java +++ b/src/main/java/dev/vality/hooker/exception/RemoteHostException.java @@ -21,4 +21,4 @@ public class RemoteHostException extends RuntimeException { boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } -} +} \ No newline at end of file diff --git a/src/main/java/dev/vality/hooker/handler/Handler.java b/src/main/java/dev/vality/hooker/handler/Handler.java deleted file mode 100644 index 29fd7cf..0000000 --- a/src/main/java/dev/vality/hooker/handler/Handler.java +++ /dev/null @@ -1,18 +0,0 @@ -package dev.vality.hooker.handler; - -import dev.vality.geck.filter.Filter; -import dev.vality.hooker.model.EventInfo; -import dev.vality.hooker.model.Message; - -/** - * Created by inal on 24.11.2016. - */ -public interface Handler { - default boolean accept(C change) { - return getFilter().match(change); - } - - void handle(C change, EventInfo eventInfo); - - Filter getFilter(); -} diff --git a/src/main/java/dev/vality/hooker/handler/Mapper.java b/src/main/java/dev/vality/hooker/handler/Mapper.java index 6f43fd3..9eec97e 100644 --- a/src/main/java/dev/vality/hooker/handler/Mapper.java +++ b/src/main/java/dev/vality/hooker/handler/Mapper.java @@ -2,17 +2,14 @@ package dev.vality.hooker.handler; import dev.vality.geck.filter.Filter; import dev.vality.hooker.model.EventInfo; -import dev.vality.hooker.model.InvoicingMessageKey; import dev.vality.hooker.model.Message; -import java.util.Map; - public interface Mapper { default boolean accept(C change) { return getFilter().match(change); } - M handle(C change, EventInfo eventInfo, Map storage); + M map(C change, EventInfo eventInfo); Filter getFilter(); -} +} \ No newline at end of file diff --git a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingFailedHandler.java b/src/main/java/dev/vality/hooker/handler/customer/CustomerBindingFailedMapper.java similarity index 61% rename from src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingFailedHandler.java rename to src/main/java/dev/vality/hooker/handler/customer/CustomerBindingFailedMapper.java index 9a86af2..2f5b212 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingFailedHandler.java +++ b/src/main/java/dev/vality/hooker/handler/customer/CustomerBindingFailedMapper.java @@ -1,31 +1,24 @@ -package dev.vality.hooker.handler.poller.customer; +package dev.vality.hooker.handler.customer; import dev.vality.geck.filter.Filter; import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.dao.impl.CustomerQueueDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; import dev.vality.hooker.model.CustomerMessageEnum; import dev.vality.hooker.model.EventType; import org.springframework.stereotype.Component; -/** - * Created by inalarsanukaev on 12.10.17. - */ @Component -public class CustomerBindingFailedHandler extends NeedReadCustomerEventHandler { +public class CustomerBindingFailedMapper extends NeedReadCustomerEventMapper { private EventType eventType = EventType.CUSTOMER_BINDING_FAILED; private Filter filter = new PathConditionFilter(new PathConditionRule(eventType.getThriftPath(), new IsNullCondition().not())); - public CustomerBindingFailedHandler(CustomerDaoImpl customerDao, - CustomerQueueDao customerQueueDao, - CustomerTaskDao customerTaskDao) { - super(customerDao, customerQueueDao, customerTaskDao); + public CustomerBindingFailedMapper(CustomerDaoImpl customerDao) { + super(customerDao); } @Override diff --git a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingStartedHandler.java b/src/main/java/dev/vality/hooker/handler/customer/CustomerBindingStartedMapper.java similarity index 70% rename from src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingStartedHandler.java rename to src/main/java/dev/vality/hooker/handler/customer/CustomerBindingStartedMapper.java index b9a0df0..446197c 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingStartedHandler.java +++ b/src/main/java/dev/vality/hooker/handler/customer/CustomerBindingStartedMapper.java @@ -1,4 +1,4 @@ -package dev.vality.hooker.handler.poller.customer; +package dev.vality.hooker.handler.customer; import dev.vality.damsel.payment_processing.CustomerChange; import dev.vality.geck.filter.Filter; @@ -6,29 +6,21 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.dao.impl.CustomerQueueDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; import dev.vality.hooker.model.CustomerMessage; import dev.vality.hooker.model.CustomerMessageEnum; import dev.vality.hooker.model.EventType; import org.springframework.stereotype.Component; - -/** - * Created by inalarsanukaev on 12.10.17. - */ @Component -public class CustomerBindingStartedHandler extends NeedReadCustomerEventHandler { +public class CustomerBindingStartedMapper extends NeedReadCustomerEventMapper { private EventType eventType = EventType.CUSTOMER_BINDING_STARTED; private Filter filter = new PathConditionFilter(new PathConditionRule(eventType.getThriftPath(), new IsNullCondition().not())); - public CustomerBindingStartedHandler(CustomerDaoImpl customerDao, - CustomerQueueDao customerQueueDao, - CustomerTaskDao customerTaskDao) { - super(customerDao, customerQueueDao, customerTaskDao); + public CustomerBindingStartedMapper(CustomerDaoImpl customerDao) { + super(customerDao); } @Override diff --git a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingSucceededHandler.java b/src/main/java/dev/vality/hooker/handler/customer/CustomerBindingSucceededMapper.java similarity index 61% rename from src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingSucceededHandler.java rename to src/main/java/dev/vality/hooker/handler/customer/CustomerBindingSucceededMapper.java index 5c399e5..92c7987 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerBindingSucceededHandler.java +++ b/src/main/java/dev/vality/hooker/handler/customer/CustomerBindingSucceededMapper.java @@ -1,31 +1,24 @@ -package dev.vality.hooker.handler.poller.customer; +package dev.vality.hooker.handler.customer; import dev.vality.geck.filter.Filter; import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.dao.impl.CustomerQueueDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; import dev.vality.hooker.model.CustomerMessageEnum; import dev.vality.hooker.model.EventType; import org.springframework.stereotype.Component; -/** - * Created by inalarsanukaev on 12.10.17. - */ @Component -public class CustomerBindingSucceededHandler extends NeedReadCustomerEventHandler { +public class CustomerBindingSucceededMapper extends NeedReadCustomerEventMapper { private EventType eventType = EventType.CUSTOMER_BINDING_SUCCEEDED; private Filter filter = new PathConditionFilter(new PathConditionRule(eventType.getThriftPath(), new IsNullCondition().not())); - public CustomerBindingSucceededHandler(CustomerDaoImpl customerDao, - CustomerQueueDao customerQueueDao, - CustomerTaskDao customerTaskDao) { - super(customerDao, customerQueueDao, customerTaskDao); + public CustomerBindingSucceededMapper(CustomerDaoImpl customerDao) { + super(customerDao); } @Override diff --git a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerCreatedHandler.java b/src/main/java/dev/vality/hooker/handler/customer/CustomerCreatedMapper.java similarity index 61% rename from src/main/java/dev/vality/hooker/handler/poller/customer/CustomerCreatedHandler.java rename to src/main/java/dev/vality/hooker/handler/customer/CustomerCreatedMapper.java index dc633fd..b811fd7 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerCreatedHandler.java +++ b/src/main/java/dev/vality/hooker/handler/customer/CustomerCreatedMapper.java @@ -1,14 +1,12 @@ -package dev.vality.hooker.handler.poller.customer; +package dev.vality.hooker.handler.customer; import dev.vality.damsel.payment_processing.CustomerChange; import dev.vality.geck.filter.Filter; import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; -import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.dao.impl.CustomerQueueDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; import dev.vality.hooker.exception.DaoException; +import dev.vality.hooker.handler.Mapper; import dev.vality.hooker.model.CustomerMessage; import dev.vality.hooker.model.CustomerMessageEnum; import dev.vality.hooker.model.EventInfo; @@ -16,16 +14,10 @@ import dev.vality.hooker.model.EventType; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -/** - * Created by inalarsanukaev on 12.10.17. - */ @Component @RequiredArgsConstructor -public class CustomerCreatedHandler extends AbstractCustomerEventHandler { +public class CustomerCreatedMapper implements Mapper { - private final CustomerDaoImpl customerDao; - private final CustomerQueueDao customerQueueDao; - private final CustomerTaskDao customerTaskDao; private EventType eventType = EventType.CUSTOMER_CREATED; private Filter filter = new PathConditionFilter(new PathConditionRule(eventType.getThriftPath(), new IsNullCondition().not())); @@ -36,23 +28,17 @@ public class CustomerCreatedHandler extends AbstractCustomerEventHandler { } @Override - protected void saveEvent(CustomerChange cc, EventInfo eventInfo) throws DaoException { + public CustomerMessage map(CustomerChange cc, EventInfo eventInfo) throws DaoException { dev.vality.damsel.payment_processing.CustomerCreated customerCreatedOrigin = cc.getCustomerCreated(); CustomerMessage customerMessage = new CustomerMessage(); - customerMessage.setEventId(eventInfo.getEventId()); customerMessage.setEventTime(eventInfo.getEventCreatedAt()); customerMessage.setSequenceId(eventInfo.getSequenceId()); customerMessage.setChangeId(eventInfo.getChangeId()); customerMessage.setType(CustomerMessageEnum.CUSTOMER); customerMessage.setPartyId(customerCreatedOrigin.getOwnerId()); customerMessage.setEventType(eventType); - customerMessage.setCustomerId(customerCreatedOrigin.getCustomerId()); + customerMessage.setSourceId(customerCreatedOrigin.getCustomerId()); customerMessage.setShopId(customerCreatedOrigin.getShopId()); - Long messageId = customerDao.create(customerMessage); - if (messageId != null) { - customerMessage.setId(messageId); - customerQueueDao.createWithPolicy(messageId); - customerTaskDao.create(messageId); - } + return customerMessage; } } diff --git a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerDeletedHandler.java b/src/main/java/dev/vality/hooker/handler/customer/CustomerDeletedMapper.java similarity index 62% rename from src/main/java/dev/vality/hooker/handler/poller/customer/CustomerDeletedHandler.java rename to src/main/java/dev/vality/hooker/handler/customer/CustomerDeletedMapper.java index 79b918c..953dc68 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerDeletedHandler.java +++ b/src/main/java/dev/vality/hooker/handler/customer/CustomerDeletedMapper.java @@ -1,31 +1,24 @@ -package dev.vality.hooker.handler.poller.customer; +package dev.vality.hooker.handler.customer; import dev.vality.geck.filter.Filter; import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.dao.impl.CustomerQueueDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; import dev.vality.hooker.model.CustomerMessageEnum; import dev.vality.hooker.model.EventType; import org.springframework.stereotype.Component; -/** - * Created by inalarsanukaev on 12.10.17. - */ @Component -public class CustomerDeletedHandler extends NeedReadCustomerEventHandler { +public class CustomerDeletedMapper extends NeedReadCustomerEventMapper { private EventType eventType = EventType.CUSTOMER_DELETED; private Filter filter = new PathConditionFilter(new PathConditionRule(eventType.getThriftPath(), new IsNullCondition().not())); - public CustomerDeletedHandler(CustomerDaoImpl customerDao, - CustomerQueueDao customerQueueDao, - CustomerTaskDao customerTaskDao) { - super(customerDao, customerQueueDao, customerTaskDao); + public CustomerDeletedMapper(CustomerDaoImpl customerDao) { + super(customerDao); } @Override diff --git a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerReadyHandler.java b/src/main/java/dev/vality/hooker/handler/customer/CustomerReadyMapper.java similarity index 62% rename from src/main/java/dev/vality/hooker/handler/poller/customer/CustomerReadyHandler.java rename to src/main/java/dev/vality/hooker/handler/customer/CustomerReadyMapper.java index c88f29e..40a9ff1 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/customer/CustomerReadyHandler.java +++ b/src/main/java/dev/vality/hooker/handler/customer/CustomerReadyMapper.java @@ -1,31 +1,24 @@ -package dev.vality.hooker.handler.poller.customer; +package dev.vality.hooker.handler.customer; import dev.vality.geck.filter.Filter; import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.dao.impl.CustomerQueueDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; import dev.vality.hooker.model.CustomerMessageEnum; import dev.vality.hooker.model.EventType; import org.springframework.stereotype.Component; -/** - * Created by inalarsanukaev on 12.10.17. - */ @Component -public class CustomerReadyHandler extends NeedReadCustomerEventHandler { +public class CustomerReadyMapper extends NeedReadCustomerEventMapper { private EventType eventType = EventType.CUSTOMER_READY; private Filter filter = new PathConditionFilter(new PathConditionRule(eventType.getThriftPath(), new IsNullCondition().not())); - public CustomerReadyHandler(CustomerDaoImpl customerDao, - CustomerQueueDao customerQueueDao, - CustomerTaskDao customerTaskDao) { - super(customerDao, customerQueueDao, customerTaskDao); + public CustomerReadyMapper(CustomerDaoImpl customerDao) { + super(customerDao); } @Override diff --git a/src/main/java/dev/vality/hooker/handler/poller/customer/NeedReadCustomerEventHandler.java b/src/main/java/dev/vality/hooker/handler/customer/NeedReadCustomerEventMapper.java similarity index 61% rename from src/main/java/dev/vality/hooker/handler/poller/customer/NeedReadCustomerEventHandler.java rename to src/main/java/dev/vality/hooker/handler/customer/NeedReadCustomerEventMapper.java index 7a3929e..3a227b5 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/customer/NeedReadCustomerEventHandler.java +++ b/src/main/java/dev/vality/hooker/handler/customer/NeedReadCustomerEventMapper.java @@ -1,49 +1,33 @@ -package dev.vality.hooker.handler.poller.customer; +package dev.vality.hooker.handler.customer; import dev.vality.damsel.payment_processing.CustomerChange; import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.dao.impl.CustomerQueueDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; import dev.vality.hooker.exception.DaoException; +import dev.vality.hooker.handler.Mapper; import dev.vality.hooker.model.CustomerMessage; import dev.vality.hooker.model.CustomerMessageEnum; import dev.vality.hooker.model.EventInfo; import dev.vality.hooker.model.EventType; import lombok.RequiredArgsConstructor; -/** - * Created by inalarsanukaev on 12.10.17. - */ @RequiredArgsConstructor -public abstract class NeedReadCustomerEventHandler extends AbstractCustomerEventHandler { +public abstract class NeedReadCustomerEventMapper implements Mapper { protected final CustomerDaoImpl customerDao; - private final CustomerQueueDao customerQueueDao; - - private final CustomerTaskDao customerTaskDao; - @Override - protected void saveEvent(CustomerChange cc, EventInfo eventInfo) throws DaoException { - //getAny any saved message for related invoice + public CustomerMessage map(CustomerChange cc, EventInfo eventInfo) throws DaoException { CustomerMessage message = getCustomerMessage(eventInfo.getSourceId()); if (message == null) { throw new DaoException("CustomerMessage for customer with id " + eventInfo.getSourceId() + " not exist"); } message.setEventType(getEventType()); message.setType(getMessageType()); - message.setEventId(eventInfo.getEventId()); message.setEventTime(eventInfo.getEventCreatedAt()); message.setSequenceId(eventInfo.getSequenceId()); message.setChangeId(eventInfo.getChangeId()); modifyMessage(cc, message); - - Long messageId = customerDao.create(message); - if (messageId != null) { - message.setId(messageId); - customerQueueDao.createWithPolicy(messageId); - customerTaskDao.create(messageId); - } + return message; } protected CustomerMessage getCustomerMessage(String customerId) { diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/AdjustmentStatusChangedMapper.java b/src/main/java/dev/vality/hooker/handler/invoicing/AdjustmentStatusChangedMapper.java similarity index 88% rename from src/main/java/dev/vality/hooker/handler/poller/invoicing/AdjustmentStatusChangedMapper.java rename to src/main/java/dev/vality/hooker/handler/invoicing/AdjustmentStatusChangedMapper.java index b6c25f5..7b12186 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/AdjustmentStatusChangedMapper.java +++ b/src/main/java/dev/vality/hooker/handler/invoicing/AdjustmentStatusChangedMapper.java @@ -1,4 +1,4 @@ -package dev.vality.hooker.handler.poller.invoicing; +package dev.vality.hooker.handler.invoicing; import dev.vality.damsel.payment_processing.InvoiceChange; import dev.vality.damsel.payment_processing.InvoicePayment; @@ -7,11 +7,7 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.InvoicingMessageDao; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.model.PaymentStatusEnum; +import dev.vality.hooker.model.*; import dev.vality.hooker.service.HellgateInvoicingService; import org.springframework.stereotype.Component; diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoiceCreatedMapper.java b/src/main/java/dev/vality/hooker/handler/invoicing/InvoiceCreatedMapper.java similarity index 68% rename from src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoiceCreatedMapper.java rename to src/main/java/dev/vality/hooker/handler/invoicing/InvoiceCreatedMapper.java index caa3011..a215392 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoiceCreatedMapper.java +++ b/src/main/java/dev/vality/hooker/handler/invoicing/InvoiceCreatedMapper.java @@ -1,4 +1,4 @@ -package dev.vality.hooker.handler.poller.invoicing; +package dev.vality.hooker.handler.invoicing; import dev.vality.damsel.domain.Invoice; import dev.vality.damsel.payment_processing.InvoiceChange; @@ -7,19 +7,13 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.model.EventInfo; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoiceStatusEnum; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; +import dev.vality.hooker.handler.Mapper; +import dev.vality.hooker.model.*; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import java.util.Map; - @Component -public class InvoiceCreatedMapper extends AbstractInvoiceEventMapper { +public class InvoiceCreatedMapper implements Mapper { private EventType eventType = EventType.INVOICE_CREATED; @@ -28,8 +22,7 @@ public class InvoiceCreatedMapper extends AbstractInvoiceEventMapper { @Override @Transactional - public InvoicingMessage buildEvent(InvoiceChange ic, EventInfo eventInfo, - Map storage) throws DaoException { + public InvoicingMessage map(InvoiceChange ic, EventInfo eventInfo) throws DaoException { Invoice invoiceOrigin = ic.getInvoiceCreated().getInvoice(); InvoicingMessage message = new InvoicingMessage(); message.setEventTime(eventInfo.getEventCreatedAt()); @@ -38,7 +31,7 @@ public class InvoiceCreatedMapper extends AbstractInvoiceEventMapper { message.setType(InvoicingMessageEnum.INVOICE); message.setPartyId(invoiceOrigin.getOwnerId()); message.setEventType(eventType); - message.setInvoiceId(invoiceOrigin.getId()); + message.setSourceId(invoiceOrigin.getId()); message.setShopId(invoiceOrigin.getShopId()); message.setInvoiceStatus(InvoiceStatusEnum.lookup(invoiceOrigin.getStatus().getSetField().getFieldName())); return message; diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentRefundStartedMapper.java b/src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentRefundStartedMapper.java similarity index 87% rename from src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentRefundStartedMapper.java rename to src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentRefundStartedMapper.java index 28fcf8c..620627a 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentRefundStartedMapper.java +++ b/src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentRefundStartedMapper.java @@ -1,4 +1,4 @@ -package dev.vality.hooker.handler.poller.invoicing; +package dev.vality.hooker.handler.invoicing; import dev.vality.damsel.domain.InvoicePaymentRefund; import dev.vality.damsel.payment_processing.InvoiceChange; @@ -8,11 +8,7 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.InvoicingMessageDao; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.model.RefundStatusEnum; +import dev.vality.hooker.model.*; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentRefundStatusChangedMapper.java b/src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentRefundStatusChangedMapper.java similarity index 86% rename from src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentRefundStatusChangedMapper.java rename to src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentRefundStatusChangedMapper.java index dd9dc12..741b295 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentRefundStatusChangedMapper.java +++ b/src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentRefundStatusChangedMapper.java @@ -1,4 +1,4 @@ -package dev.vality.hooker.handler.poller.invoicing; +package dev.vality.hooker.handler.invoicing; import dev.vality.damsel.payment_processing.InvoiceChange; import dev.vality.geck.filter.Filter; @@ -6,11 +6,7 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.InvoicingMessageDao; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.model.RefundStatusEnum; +import dev.vality.hooker.model.*; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentStartedMapper.java b/src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentStartedMapper.java similarity index 85% rename from src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentStartedMapper.java rename to src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentStartedMapper.java index d3958de..f58ba0b 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentStartedMapper.java +++ b/src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentStartedMapper.java @@ -1,4 +1,4 @@ -package dev.vality.hooker.handler.poller.invoicing; +package dev.vality.hooker.handler.invoicing; import dev.vality.damsel.domain.InvoicePayment; import dev.vality.damsel.payment_processing.InvoiceChange; @@ -7,11 +7,7 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.InvoicingMessageDao; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.model.PaymentStatusEnum; +import dev.vality.hooker.model.*; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentStatusChangedMapper.java b/src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentStatusChangedMapper.java similarity index 86% rename from src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentStatusChangedMapper.java rename to src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentStatusChangedMapper.java index 9de23de..33a8757 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoicePaymentStatusChangedMapper.java +++ b/src/main/java/dev/vality/hooker/handler/invoicing/InvoicePaymentStatusChangedMapper.java @@ -1,4 +1,4 @@ -package dev.vality.hooker.handler.poller.invoicing; +package dev.vality.hooker.handler.invoicing; import dev.vality.damsel.payment_processing.InvoiceChange; import dev.vality.geck.filter.Filter; @@ -6,11 +6,7 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.InvoicingMessageDao; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.model.PaymentStatusEnum; +import dev.vality.hooker.model.*; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoiceStatusChangedMapper.java b/src/main/java/dev/vality/hooker/handler/invoicing/InvoiceStatusChangedMapper.java similarity index 84% rename from src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoiceStatusChangedMapper.java rename to src/main/java/dev/vality/hooker/handler/invoicing/InvoiceStatusChangedMapper.java index 6e2fd24..3a16fe7 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/InvoiceStatusChangedMapper.java +++ b/src/main/java/dev/vality/hooker/handler/invoicing/InvoiceStatusChangedMapper.java @@ -1,4 +1,4 @@ -package dev.vality.hooker.handler.poller.invoicing; +package dev.vality.hooker.handler.invoicing; import dev.vality.damsel.payment_processing.InvoiceChange; import dev.vality.geck.filter.Filter; @@ -6,11 +6,7 @@ import dev.vality.geck.filter.PathConditionFilter; import dev.vality.geck.filter.condition.IsNullCondition; import dev.vality.geck.filter.rule.PathConditionRule; import dev.vality.hooker.dao.InvoicingMessageDao; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoiceStatusEnum; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; +import dev.vality.hooker.model.*; import org.springframework.stereotype.Component; @Component diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/NeedReadInvoiceEventMapper.java b/src/main/java/dev/vality/hooker/handler/invoicing/NeedReadInvoiceEventMapper.java similarity index 63% rename from src/main/java/dev/vality/hooker/handler/poller/invoicing/NeedReadInvoiceEventMapper.java rename to src/main/java/dev/vality/hooker/handler/invoicing/NeedReadInvoiceEventMapper.java index f480b72..b3ecc8c 100644 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/NeedReadInvoiceEventMapper.java +++ b/src/main/java/dev/vality/hooker/handler/invoicing/NeedReadInvoiceEventMapper.java @@ -1,35 +1,26 @@ -package dev.vality.hooker.handler.poller.invoicing; +package dev.vality.hooker.handler.invoicing; import dev.vality.damsel.payment_processing.InvoiceChange; import dev.vality.hooker.dao.InvoicingMessageDao; import dev.vality.hooker.exception.DaoException; import dev.vality.hooker.exception.NotFoundException; -import dev.vality.hooker.model.EventInfo; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; +import dev.vality.hooker.handler.Mapper; +import dev.vality.hooker.model.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import java.util.Map; - @Slf4j @RequiredArgsConstructor -public abstract class NeedReadInvoiceEventMapper extends AbstractInvoiceEventMapper { +public abstract class NeedReadInvoiceEventMapper implements Mapper { private final InvoicingMessageDao messageDao; @Override - protected InvoicingMessage buildEvent(InvoiceChange ic, EventInfo eventInfo, - Map storage) throws DaoException { + public InvoicingMessage map(InvoiceChange ic, EventInfo eventInfo) throws DaoException { InvoicingMessage message; InvoicingMessageKey messageKey = getMessageKey(eventInfo.getSourceId(), ic); try { - message = storage.get(messageKey); - if (message == null) { - message = messageDao.getInvoicingMessage(messageKey); - } + message = messageDao.getInvoicingMessage(messageKey); message = message.copy(); } catch (NotFoundException e) { log.warn(e.getMessage()); diff --git a/src/main/java/dev/vality/hooker/handler/poller/customer/AbstractCustomerEventHandler.java b/src/main/java/dev/vality/hooker/handler/poller/customer/AbstractCustomerEventHandler.java deleted file mode 100644 index bca5b0d..0000000 --- a/src/main/java/dev/vality/hooker/handler/poller/customer/AbstractCustomerEventHandler.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.vality.hooker.handler.poller.customer; - -import dev.vality.damsel.payment_processing.CustomerChange; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.handler.Handler; -import dev.vality.hooker.model.CustomerMessage; -import dev.vality.hooker.model.EventInfo; - -/** - * Created by inalarsanukaev on 07.04.17. - */ -public abstract class AbstractCustomerEventHandler implements Handler { - - @Override - public void handle(CustomerChange c, EventInfo eventInfo) throws DaoException { - saveEvent(c, eventInfo); - } - - protected abstract void saveEvent(CustomerChange cc, EventInfo eventInfo) throws DaoException; -} diff --git a/src/main/java/dev/vality/hooker/handler/poller/invoicing/AbstractInvoiceEventMapper.java b/src/main/java/dev/vality/hooker/handler/poller/invoicing/AbstractInvoiceEventMapper.java deleted file mode 100644 index 3595424..0000000 --- a/src/main/java/dev/vality/hooker/handler/poller/invoicing/AbstractInvoiceEventMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.vality.hooker.handler.poller.invoicing; - -import dev.vality.damsel.payment_processing.InvoiceChange; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.handler.Mapper; -import dev.vality.hooker.model.EventInfo; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageKey; - -import java.util.Map; - -public abstract class AbstractInvoiceEventMapper implements Mapper { - - @Override - public InvoicingMessage handle(InvoiceChange ic, EventInfo eventInfo, - Map storage) throws DaoException { - return buildEvent(ic, eventInfo, storage); - } - - protected abstract InvoicingMessage buildEvent(InvoiceChange ic, EventInfo eventInfo, - Map storage) - throws DaoException; -} diff --git a/src/main/java/dev/vality/hooker/listener/CustomerMachineEventHandler.java b/src/main/java/dev/vality/hooker/listener/CustomerMachineEventHandler.java index 0f8df3a..fc0e8e6 100644 --- a/src/main/java/dev/vality/hooker/listener/CustomerMachineEventHandler.java +++ b/src/main/java/dev/vality/hooker/listener/CustomerMachineEventHandler.java @@ -2,11 +2,10 @@ package dev.vality.hooker.listener; import dev.vality.damsel.payment_processing.CustomerChange; import dev.vality.damsel.payment_processing.EventPayload; -import dev.vality.geck.serializer.kit.json.JsonHandler; -import dev.vality.geck.serializer.kit.tbase.TBaseProcessor; -import dev.vality.hooker.handler.Handler; -import dev.vality.hooker.handler.poller.customer.AbstractCustomerEventHandler; +import dev.vality.hooker.handler.Mapper; +import dev.vality.hooker.model.CustomerMessage; import dev.vality.hooker.model.EventInfo; +import dev.vality.hooker.service.MessageService; import dev.vality.machinegun.eventsink.MachineEvent; import dev.vality.sink.common.parser.impl.MachineEventParser; import lombok.RequiredArgsConstructor; @@ -23,48 +22,39 @@ import java.util.List; public class CustomerMachineEventHandler implements MachineEventHandler { private final MachineEventParser parser; - private final List pollingEventHandlers; + private final List > customerEventMappers; + private final MessageService customerMessageService; @Override @Transactional public void handle(List machineEvents, Acknowledgment ack) { - for (MachineEvent machineEvent : machineEvents) { - EventPayload payload = parser.parse(machineEvent); - if (!payload.isSetCustomerChanges()) { - return; + machineEvents.forEach(me -> { + EventPayload payload = parser.parse(me); + if (payload.isSetCustomerChanges()) { + handleChanges(me, payload); } - - List changes = payload.getCustomerChanges(); - for (int i = 0; i < changes.size(); ++i) { - preparePollingHandlers(changes.get(i), machineEvent, i); - } - } + }); ack.acknowledge(); } - private void preparePollingHandlers(CustomerChange cc, MachineEvent machineEvent, int i) { - pollingEventHandlers.stream() - .filter(handler -> handler.accept(cc)) - .findFirst() - .ifPresent(handler -> processEvent(handler, cc, machineEvent, i)); - } - - private void processEvent(Handler pollingEventHandler, Object cc, MachineEvent machineEvent, int i) { - long id = machineEvent.getEventId(); - try { - log.info("We got an event {}", new TBaseProcessor() - .process(machineEvent, JsonHandler.newPrettyJsonInstance())); - EventInfo eventInfo = new EventInfo( - machineEvent.getEventId(), - machineEvent.getCreatedAt(), - machineEvent.getSourceId(), - machineEvent.getEventId(), - i - ); - pollingEventHandler.handle(cc, eventInfo); - } catch (Exception e) { - log.error("Error when poller handling with id {}", id, e); + private void handleChanges(MachineEvent me, EventPayload payload) { + for (int i = 0; i < payload.getCustomerChanges().size(); ++i) { + CustomerChange customerChange = payload.getCustomerChanges().get(i); + handleChange(me, customerChange, i); } } + private void handleChange(MachineEvent me, CustomerChange customerChange, int i) { + customerEventMappers.stream() + .filter(handler -> handler.accept(customerChange)) + .findFirst() + .ifPresent(handler -> { + log.info("Start to handle event {}", customerChange); + var eventInfo = new EventInfo(me.getCreatedAt(), me.getSourceId(), me.getEventId(), i); + CustomerMessage message = handler.map(customerChange, eventInfo); + if (message != null) { + customerMessageService.process(message); + } + }); + } } diff --git a/src/main/java/dev/vality/hooker/listener/InvoicingMachineEventHandler.java b/src/main/java/dev/vality/hooker/listener/InvoicingMachineEventHandler.java index b549aa4..a969fe3 100644 --- a/src/main/java/dev/vality/hooker/listener/InvoicingMachineEventHandler.java +++ b/src/main/java/dev/vality/hooker/listener/InvoicingMachineEventHandler.java @@ -2,12 +2,11 @@ package dev.vality.hooker.listener; import dev.vality.damsel.payment_processing.EventPayload; import dev.vality.damsel.payment_processing.InvoiceChange; +import dev.vality.hooker.handler.Mapper; import dev.vality.hooker.model.EventInfo; import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.service.BatchService; import dev.vality.hooker.service.HandlerManager; -import dev.vality.hooker.utils.KeyUtils; +import dev.vality.hooker.service.MessageService; import dev.vality.machinegun.eventsink.MachineEvent; import dev.vality.sink.common.parser.impl.MachineEventParser; import lombok.RequiredArgsConstructor; @@ -16,47 +15,47 @@ import org.springframework.kafka.support.Acknowledgment; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; @Slf4j @Component @RequiredArgsConstructor public class InvoicingMachineEventHandler implements MachineEventHandler { - private final HandlerManager handlerManager; + private final List > handlers; private final MachineEventParser parser; - private final BatchService batchService; + private final MessageService invoicingMessageService; @Override @Transactional public void handle(List machineEvents, Acknowledgment ack) { - List messages = new ArrayList<>(); - Map localCache = new HashMap<>(); machineEvents.forEach(me -> { EventPayload payload = parser.parse(me); if (payload.isSetInvoiceChanges()) { - for (int i = 0; i < payload.getInvoiceChanges().size(); ++i) { - InvoiceChange invoiceChange = payload.getInvoiceChanges().get(i); - int j = i; - handlerManager.getHandler(invoiceChange).ifPresent(handler -> { - log.info("Start to handle event {}", invoiceChange); - InvoicingMessage message = handler.handle(invoiceChange, - new EventInfo(null, me.getCreatedAt(), me.getSourceId(), me.getEventId(), j), - localCache); - if (message != null) { - localCache.put(KeyUtils.key(message), message); - messages.add(message); - } - }); - } + handleChanges(me, payload); } }); - if (!localCache.isEmpty()) { - batchService.process(messages); - } ack.acknowledge(); } + + private void handleChanges(MachineEvent me, EventPayload payload) { + for (int i = 0; i < payload.getInvoiceChanges().size(); ++i) { + InvoiceChange invoiceChange = payload.getInvoiceChanges().get(i); + handleChange(me, invoiceChange, i); + } + } + + private void handleChange(MachineEvent me, InvoiceChange invoiceChange, int i) { + handlers.stream() + .filter(handler -> handler.accept(invoiceChange)) + .findFirst() + .ifPresent(handler -> { + log.info("Start to handle event {}", invoiceChange); + var eventInfo = new EventInfo(me.getCreatedAt(), me.getSourceId(), me.getEventId(), i); + InvoicingMessage message = handler.map(invoiceChange, eventInfo); + if (message != null) { + invoicingMessageService.process(message); + } + }); + } } diff --git a/src/main/java/dev/vality/hooker/logging/HttpLoggingInterceptor.java b/src/main/java/dev/vality/hooker/logging/HttpLoggingInterceptor.java deleted file mode 100644 index 38baaec..0000000 --- a/src/main/java/dev/vality/hooker/logging/HttpLoggingInterceptor.java +++ /dev/null @@ -1,285 +0,0 @@ -package dev.vality.hooker.logging; - -import lombok.extern.slf4j.Slf4j; -import okhttp3.Connection; -import okhttp3.Headers; -import okhttp3.Interceptor; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; -import okhttp3.ResponseBody; -import okhttp3.internal.http.HttpHeaders; -import okio.Buffer; -import okio.BufferedSource; - -import java.io.EOFException; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.concurrent.TimeUnit; - -/** - * An OkHttp interceptor which logs request and response information. Can be applied as an - * {@linkplain OkHttpClient#interceptors() application interceptor} or as a {@linkplain - * OkHttpClient#networkInterceptors() network interceptor}. The format of the logs created by - * this class should not be considered stable and may change slightly between releases. If you need - * a stable logging format, use your own interceptor. - */ -@Slf4j -public final class HttpLoggingInterceptor implements Interceptor { - private static final Charset UTF8 = Charset.forName("UTF-8"); - private final Logger logger; - private volatile Level level = Level.BASIC; - - public HttpLoggingInterceptor() { - this(Logger.DEFAULT); - } - - public HttpLoggingInterceptor(Logger logger) { - this.logger = logger; - } - - /** - * Returns true if the body in question probably contains human readable text. Uses a small sample - * of code points to detect unicode control characters commonly used in binary file signatures. - */ - static boolean isPlaintext(Buffer buffer) { - try { - Buffer prefix = new Buffer(); - long byteCount = buffer.size() < 64 ? buffer.size() : 64; - buffer.copyTo(prefix, 0, byteCount); - for (int i = 0; i < 16; i++) { - if (prefix.exhausted()) { - break; - } - int codePoint = prefix.readUtf8CodePoint(); - if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { - return false; - } - } - return true; - } catch (EOFException e) { - return false; // Truncated UTF-8 sequence. - } - } - - public Level getLevel() { - return level; - } - - /** - * Change the level at which this interceptor logs. - */ - public HttpLoggingInterceptor setLevel(Level level) { - if (level == null) { - throw new NullPointerException("level == null. Use Level.NONE instead."); - } - this.level = level; - return this; - } - - @Override - public Response intercept(Chain chain) throws IOException { - Level level = this.level; - - Request request = chain.request(); - if (level == Level.NONE) { - return chain.proceed(request); - } - - boolean logBody = level == Level.BODY; - boolean logHeaders = logBody || level == Level.HEADERS; - - RequestBody requestBody = request.body(); - boolean hasRequestBody = requestBody != null; - - Connection connection = chain.connection(); - StringBuilder message = new StringBuilder("--> \n") - .append(request.method()) - .append(' ').append(request.url()) - .append(connection != null ? " " + connection.protocol() : "").append('\n'); - if (!logHeaders && hasRequestBody) { - message.append(" (").append(requestBody.contentLength()).append("-byte body)").append('\n'); - } - //logger.log(requestStartMessage); - - if (logHeaders) { - if (hasRequestBody) { - // Request body headers are only present when installed as a network interceptor. Force - // them to be included (when available) so there values are known. - if (requestBody.contentType() != null) { - message.append("Content-Type: ").append(requestBody.contentType()).append('\n'); - } - if (requestBody.contentLength() != -1) { - message.append("Content-Length: ").append(requestBody.contentLength()).append('\n'); - } - } - - Headers headers = request.headers(); - for (int i = 0, count = headers.size(); i < count; i++) { - String name = headers.name(i); - // Skip headers from the request body as they are explicitly logged above. - if (!"Authorization".equalsIgnoreCase(name)) { - message.append(name).append(": ").append(headers.value(i)).append('\n'); - } - } - - if (!logBody || !hasRequestBody) { - message.append("\n--> END ").append(request.method()); - } else if (bodyEncoded(request.headers())) { - message.append("\n--> END ").append(request.method()).append(" (encoded body omitted)"); - } else { - message.append('\n'); - Buffer buffer = new Buffer(); - requestBody.writeTo(buffer); - - Charset charset = UTF8; - MediaType contentType = requestBody.contentType(); - if (contentType != null) { - charset = contentType.charset(UTF8); - } - - if (isPlaintext(buffer)) { - message.append(buffer.readString(charset)); - message.append("\n--> END ").append(request.method()) - .append(" (").append(requestBody.contentLength()).append("-byte body)"); - } else { - message.append("\n--> END ").append(request.method()).append(" (binary ") - .append(requestBody.contentLength()).append("-byte body omitted)"); - } - } - } - logger.log(message.toString()); - long startNs = System.nanoTime(); - Response response; - try { - response = chain.proceed(request); - } catch (Exception e) { - logger.log("<-- HTTP FAILED: " + e); - throw e; - } - long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs); - - ResponseBody responseBody = response.body(); - long contentLength = responseBody.contentLength(); - message = new StringBuilder(); - String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length"; - message.append("<-- \n") - .append(response.code()) - .append(response.message().isEmpty() ? "" : " " + response.message()) - .append(' ').append(response.request().url()) - .append(" (").append(tookMs).append("ms").append((!logHeaders ? ", " + bodySize + " body" : "") + ')') - .append('\n'); - - if (logHeaders) { - Headers headers = response.headers(); - for (int i = 0, count = headers.size(); i < count; i++) { - message.append(headers.name(i)).append(": ").append(headers.value(i)).append('\n'); - } - - if (!logBody || !HttpHeaders.hasBody(response)) { - message.append("\n<-- END HTTP"); - } else if (bodyEncoded(response.headers())) { - message.append("\n<-- END HTTP (encoded body omitted)"); - } else { - message.append('\n'); - BufferedSource source = responseBody.source(); - source.request(Long.MAX_VALUE); // Buffer the entire body. - Buffer buffer = source.buffer(); - - Charset charset = UTF8; - MediaType contentType = responseBody.contentType(); - if (contentType != null) { - charset = contentType.charset(UTF8); - } - - if (!isPlaintext(buffer)) { - message.append("\n<-- END HTTP (binary ").append(buffer.size()).append("-byte body omitted)"); - return response; - } - - if (contentLength != 0) { - message.append(buffer.clone().readString(charset)); - } - - logger.log(message.append("\n<-- END HTTP (").append(buffer.size()).append("-byte body)").toString()); - } - } - - return response; - } - - private boolean bodyEncoded(Headers headers) { - String contentEncoding = headers.get("Content-Encoding"); - return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity"); - } - - public enum Level { - /** - * No logs. - */ - NONE, - /** - * Logs request and response lines. - *
- *
Example: - *
{@code - * --> POST /greeting http/1.1 (3-byte body) - * - * <-- 200 OK (22ms, 6-byte body) - * }- */ - BASIC, - /** - * Logs request and response lines and their respective headers. - *- *
Example: - *
{@code - * --> POST /greeting http/1.1 - * Host: example.com - * Content-Type: plain/text - * Content-Length: 3 - * --> END POST - * - * <-- 200 OK (22ms) - * Content-Type: plain/text - * Content-Length: 6 - * <-- END HTTP - * }- */ - HEADERS, - /** - * Logs request and response lines and their respective headers and bodies (if present). - *- *
Example: - *
{@code - * --> POST /greeting http/1.1 - * Host: example.com - * Content-Type: plain/text - * Content-Length: 3 - * - * Hi? - * --> END POST - * - * <-- 200 OK (22ms) - * Content-Type: plain/text - * Content-Length: 6 - * - * Hello! - * <-- END HTTP - * }- */ - BODY - } - - public interface Logger { - /** - * A {@link Logger} defaults output appropriate for the current platform. - */ - Logger DEFAULT = log::info; - - void log(String message); - } -} - diff --git a/src/main/java/dev/vality/hooker/model/CustomerMessage.java b/src/main/java/dev/vality/hooker/model/CustomerMessage.java index ec34d20..0138584 100644 --- a/src/main/java/dev/vality/hooker/model/CustomerMessage.java +++ b/src/main/java/dev/vality/hooker/model/CustomerMessage.java @@ -5,16 +5,12 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.ToString; -/** - * Created by inalarsanukaev on 13.10.17. - */ @Data @AllArgsConstructor @NoArgsConstructor @ToString public class CustomerMessage extends Message { private CustomerMessageEnum type; - private String customerId; private String bindingId; public boolean isBinding() { diff --git a/src/main/java/dev/vality/hooker/model/CustomerQueue.java b/src/main/java/dev/vality/hooker/model/CustomerQueue.java index 3324acc..ba37473 100644 --- a/src/main/java/dev/vality/hooker/model/CustomerQueue.java +++ b/src/main/java/dev/vality/hooker/model/CustomerQueue.java @@ -3,9 +3,6 @@ package dev.vality.hooker.model; import lombok.Getter; import lombok.Setter; -/** - * Created by inalarsanukaev on 14.11.17. - */ @Getter @Setter public class CustomerQueue extends Queue { diff --git a/src/main/java/dev/vality/hooker/model/EventInfo.java b/src/main/java/dev/vality/hooker/model/EventInfo.java index 5df1a9c..f6fea04 100644 --- a/src/main/java/dev/vality/hooker/model/EventInfo.java +++ b/src/main/java/dev/vality/hooker/model/EventInfo.java @@ -6,7 +6,6 @@ import lombok.Data; @Data @AllArgsConstructor public class EventInfo { - private Long eventId; private String eventCreatedAt; private String sourceId; private Long sequenceId; diff --git a/src/main/java/dev/vality/hooker/model/Hook.java b/src/main/java/dev/vality/hooker/model/Hook.java index 4cf1ab3..e3c8cb0 100644 --- a/src/main/java/dev/vality/hooker/model/Hook.java +++ b/src/main/java/dev/vality/hooker/model/Hook.java @@ -1,38 +1,26 @@ package dev.vality.hooker.model; import dev.vality.hooker.dao.WebhookAdditionalFilter; -import dev.vality.hooker.retry.RetryPolicyType; -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; +import lombok.*; import java.util.Set; -/** - * Created by jeckep on 13.04.17. - */ @Data +@Builder +@ToString @AllArgsConstructor @NoArgsConstructor public class Hook { private long id; private String partyId; private String topic; + @ToString.Exclude private Setfilters; private String url; + @ToString.Exclude private String pubKey; + @ToString.Exclude private String privKey; private boolean enabled; private double availability; - private RetryPolicyType retryPolicyType; - - @Override - public String toString() { - return "Hook{" + - "id=" + id + - ", topic=" + topic + - ", partyId='" + partyId + '\'' + - ", url='" + url + '\'' + - '}'; - } } diff --git a/src/main/java/dev/vality/hooker/model/InvoicingMessage.java b/src/main/java/dev/vality/hooker/model/InvoicingMessage.java index 33b0abf..e277e7e 100644 --- a/src/main/java/dev/vality/hooker/model/InvoicingMessage.java +++ b/src/main/java/dev/vality/hooker/model/InvoicingMessage.java @@ -5,17 +5,12 @@ import lombok.NoArgsConstructor; import lombok.ToString; import org.springframework.beans.BeanUtils; - -/** - * Created by inalarsanukaev on 07.04.17. - */ @NoArgsConstructor @Data @ToString public class InvoicingMessage extends Message { private InvoicingMessageEnum type; - private String invoiceId; private InvoiceStatusEnum invoiceStatus; private String paymentId; private PaymentStatusEnum paymentStatus; diff --git a/src/main/java/dev/vality/hooker/model/InvoicingMessageEnum.java b/src/main/java/dev/vality/hooker/model/InvoicingMessageEnum.java index 9c5354f..efc6364 100644 --- a/src/main/java/dev/vality/hooker/model/InvoicingMessageEnum.java +++ b/src/main/java/dev/vality/hooker/model/InvoicingMessageEnum.java @@ -12,7 +12,7 @@ public enum InvoicingMessageEnum { PAYMENT("payment"), REFUND("refund"); - private String value; + private final String value; public static InvoicingMessageEnum lookup(String v) { return Arrays.stream(values()).filter(value -> v.equals(value.getValue())).findFirst() diff --git a/src/main/java/dev/vality/hooker/model/InvoicingMessageKey.java b/src/main/java/dev/vality/hooker/model/InvoicingMessageKey.java index 6e2f6b3..17e7b58 100644 --- a/src/main/java/dev/vality/hooker/model/InvoicingMessageKey.java +++ b/src/main/java/dev/vality/hooker/model/InvoicingMessageKey.java @@ -1,10 +1,6 @@ package dev.vality.hooker.model; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; +import lombok.*; @Data @AllArgsConstructor diff --git a/src/main/java/dev/vality/hooker/model/InvoicingQueue.java b/src/main/java/dev/vality/hooker/model/InvoicingQueue.java index b2dc6f0..8f0721e 100644 --- a/src/main/java/dev/vality/hooker/model/InvoicingQueue.java +++ b/src/main/java/dev/vality/hooker/model/InvoicingQueue.java @@ -3,9 +3,6 @@ package dev.vality.hooker.model; import lombok.Getter; import lombok.Setter; -/** - * Created by inalarsanukaev on 14.11.17. - */ @Getter @Setter public class InvoicingQueue extends Queue { diff --git a/src/main/java/dev/vality/hooker/model/Message.java b/src/main/java/dev/vality/hooker/model/Message.java index 0fa4482..175d2e4 100644 --- a/src/main/java/dev/vality/hooker/model/Message.java +++ b/src/main/java/dev/vality/hooker/model/Message.java @@ -3,17 +3,14 @@ package dev.vality.hooker.model; import lombok.Getter; import lombok.Setter; -/** - * Created by inalarsanukaev on 20.11.17. - */ @Getter @Setter public class Message { private Long id; - private Long eventId; private Long sequenceId; private Integer changeId; private String eventTime; + private String sourceId; private String partyId; private String shopId; private EventType eventType; diff --git a/src/main/java/dev/vality/hooker/model/PaymentToolDetailsDigitalWallet.java b/src/main/java/dev/vality/hooker/model/PaymentToolDetailsDigitalWallet.java deleted file mode 100644 index 70a0608..0000000 --- a/src/main/java/dev/vality/hooker/model/PaymentToolDetailsDigitalWallet.java +++ /dev/null @@ -1,14 +0,0 @@ -package dev.vality.hooker.model; - -import dev.vality.swag_webhook_events.model.DigitalWalletDetails; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -@AllArgsConstructor -public class PaymentToolDetailsDigitalWallet - extends dev.vality.swag_webhook_events.model.PaymentToolDetailsDigitalWallet { - private DigitalWalletDetails digitalWalletDetails; -} diff --git a/src/main/java/dev/vality/hooker/model/Queue.java b/src/main/java/dev/vality/hooker/model/Queue.java index 2ec8d0a..5366e04 100644 --- a/src/main/java/dev/vality/hooker/model/Queue.java +++ b/src/main/java/dev/vality/hooker/model/Queue.java @@ -1,6 +1,5 @@ package dev.vality.hooker.model; -import dev.vality.hooker.retry.RetryPolicyRecord; import lombok.Data; import lombok.NoArgsConstructor; @@ -9,5 +8,4 @@ import lombok.NoArgsConstructor; public class Queue { private long id; private Hook hook; - private RetryPolicyRecord retryPolicyRecord; } diff --git a/src/main/java/dev/vality/hooker/model/Task.java b/src/main/java/dev/vality/hooker/model/Task.java deleted file mode 100644 index 1bdbc8b..0000000 --- a/src/main/java/dev/vality/hooker/model/Task.java +++ /dev/null @@ -1,15 +0,0 @@ -package dev.vality.hooker.model; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.Setter; -import lombok.ToString; - -@AllArgsConstructor -@Getter -@Setter -@ToString -public class Task { - long messageId; - long queueId; -} diff --git a/src/main/java/dev/vality/hooker/model/WebhookMessageModel.java b/src/main/java/dev/vality/hooker/model/WebhookMessageModel.java new file mode 100644 index 0000000..a34dc00 --- /dev/null +++ b/src/main/java/dev/vality/hooker/model/WebhookMessageModel.java @@ -0,0 +1,11 @@ +package dev.vality.hooker.model; + +import lombok.Data; + +@Data +public class WebhookMessageModel { + private T message; + private Long hookId; + private String url; + private String privateKey; +} diff --git a/src/main/java/dev/vality/hooker/retry/RetryPoliciesService.java b/src/main/java/dev/vality/hooker/retry/RetryPoliciesService.java deleted file mode 100644 index 2711aa3..0000000 --- a/src/main/java/dev/vality/hooker/retry/RetryPoliciesService.java +++ /dev/null @@ -1,36 +0,0 @@ -package dev.vality.hooker.retry; - -import dev.vality.hooker.dao.SimpleRetryPolicyDao; -import dev.vality.hooker.retry.impl.simple.SimpleRetryPolicy; -import dev.vality.hooker.retry.impl.simple.SimpleRetryPolicyRecord; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -/** - * Created by jeckep on 18.04.17. - */ - -@Service -@RequiredArgsConstructor -public class RetryPoliciesService { - - private final SimpleRetryPolicy simpleRetryPolicy; - private final SimpleRetryPolicyDao simpleRetryPolicyDao; - - public RetryPolicy getRetryPolicyByType(RetryPolicyType type) { - if (RetryPolicyType.SIMPLE.equals(type)) { - return simpleRetryPolicy; - } else { - throw new UnsupportedOperationException("Retry policy for type: " + type.toString() + " not found"); - } - } - - public void update(RetryPolicyRecord record) { - if (RetryPolicyType.SIMPLE.equals(record.getType())) { - simpleRetryPolicyDao.update((SimpleRetryPolicyRecord) record); - } else { - throw new UnsupportedOperationException( - "Retry policy DAO for type: " + record.getType().toString() + " not found"); - } - } -} diff --git a/src/main/java/dev/vality/hooker/retry/RetryPolicy.java b/src/main/java/dev/vality/hooker/retry/RetryPolicy.java deleted file mode 100644 index 7ad2c0f..0000000 --- a/src/main/java/dev/vality/hooker/retry/RetryPolicy.java +++ /dev/null @@ -1,12 +0,0 @@ -package dev.vality.hooker.retry; - -/** - * Created by jeckep on 17.04.17. - */ -public interface RetryPolicy { - boolean shouldDisable(T record); - - RetryPolicyType getType(); - - void updateFailed(T record); -} diff --git a/src/main/java/dev/vality/hooker/retry/RetryPolicyRecord.java b/src/main/java/dev/vality/hooker/retry/RetryPolicyRecord.java deleted file mode 100644 index 8c1fa4c..0000000 --- a/src/main/java/dev/vality/hooker/retry/RetryPolicyRecord.java +++ /dev/null @@ -1,12 +0,0 @@ -package dev.vality.hooker.retry; - -/** - * Created by jeckep on 18.04.17. - */ -public abstract class RetryPolicyRecord { - public abstract boolean isFailed(); - - public abstract void reset(); - - public abstract RetryPolicyType getType(); -} diff --git a/src/main/java/dev/vality/hooker/retry/RetryPolicyType.java b/src/main/java/dev/vality/hooker/retry/RetryPolicyType.java deleted file mode 100644 index f083186..0000000 --- a/src/main/java/dev/vality/hooker/retry/RetryPolicyType.java +++ /dev/null @@ -1,38 +0,0 @@ -package dev.vality.hooker.retry; - -import dev.vality.hooker.retry.impl.simple.SimpleRetryPolicyRecord; - -import java.sql.ResultSet; -import java.sql.SQLException; - -/** - * Created by jeckep on 17.04.17. - */ -public enum RetryPolicyType { - /* - * Первая и самая простая политика переотправки. - * Если хук не отвечает или отвечает с ошибкой, - * пробуем 4 раза с интервалами 30сек, 5мин, 15мин, 1час опять послать - * неотправленное сообщение в этот хук. При этом очередь сообщений для хука копится. - * После первой удачной отправки, после неудачной, счетчик неудачных попыток сбрасывается. - * */ - - SIMPLE { - @Override - public RetryPolicyRecord build(ResultSet rs) throws SQLException { - SimpleRetryPolicyRecord record = new SimpleRetryPolicyRecord(); - record.setQueueId(rs.getLong("id")); - record.setMessageType(rs.getString("message_type")); - record.setFailCount(rs.getInt("fail_count")); - record.setLastFailTime(rs.getLong("last_fail_time")); - record.setNextFireTime(rs.getLong("next_fire_time_ms")); - return record; - } - - public SimpleRetryPolicyRecord cast(RetryPolicyRecord record) { - return (SimpleRetryPolicyRecord) record; - } - }; - - public abstract RetryPolicyRecord build(ResultSet rs) throws SQLException; -} diff --git a/src/main/java/dev/vality/hooker/retry/impl/simple/SimpleRetryPolicy.java b/src/main/java/dev/vality/hooker/retry/impl/simple/SimpleRetryPolicy.java deleted file mode 100644 index 39b9b64..0000000 --- a/src/main/java/dev/vality/hooker/retry/impl/simple/SimpleRetryPolicy.java +++ /dev/null @@ -1,40 +0,0 @@ -package dev.vality.hooker.retry.impl.simple; - -import dev.vality.hooker.retry.RetryPolicy; -import dev.vality.hooker.retry.RetryPolicyType; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Component; - -/** - * Created by jeckep on 17.04.17. - */ - -@Component -@RequiredArgsConstructor -public class SimpleRetryPolicy implements RetryPolicy { - - private long[] delays = {30, 300, 900, 3600, - 3600, 3600, 3600, 3600, 3600, 3600, 3600, 3600, 3600, 3600, - 3600, 3600, 3600, 3600, 3600, 3600, 3600, 3600, 3600, 3600, - 3600, 3600, 3600, 3600 - }; //in seconds - - @Override - public RetryPolicyType getType() { - return RetryPolicyType.SIMPLE; - } - - @Override - public void updateFailed(SimpleRetryPolicyRecord record) { - record.setFailCount(record.getFailCount() + 1); - record.setLastFailTime(System.currentTimeMillis()); - if (record.getFailCount() <= delays.length) { - record.setNextFireTime(record.getLastFailTime() + (delays[record.getFailCount() - 1] * 1000)); - } - } - - @Override - public boolean shouldDisable(SimpleRetryPolicyRecord rp) { - return rp.getFailCount() > delays.length; - } -} diff --git a/src/main/java/dev/vality/hooker/retry/impl/simple/SimpleRetryPolicyRecord.java b/src/main/java/dev/vality/hooker/retry/impl/simple/SimpleRetryPolicyRecord.java deleted file mode 100644 index bf33dc1..0000000 --- a/src/main/java/dev/vality/hooker/retry/impl/simple/SimpleRetryPolicyRecord.java +++ /dev/null @@ -1,41 +0,0 @@ -package dev.vality.hooker.retry.impl.simple; - -import dev.vality.hooker.retry.RetryPolicyRecord; -import dev.vality.hooker.retry.RetryPolicyType; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; -import lombok.ToString; - -@ToString -@AllArgsConstructor -@NoArgsConstructor -@Getter -@Setter -public class SimpleRetryPolicyRecord extends RetryPolicyRecord { - public static RetryPolicyType type = RetryPolicyType.SIMPLE; - - private Long queueId; - private String messageType; - private Integer failCount; - private Long lastFailTime; - private Long nextFireTime; - - @Override - public boolean isFailed() { - return failCount > 0; - } - - @Override - public void reset() { - failCount = 0; - lastFailTime = null; - nextFireTime = null; - } - - @Override - public RetryPolicyType getType() { - return type; - } -} diff --git a/src/main/java/dev/vality/hooker/scheduler/MessageScheduler.java b/src/main/java/dev/vality/hooker/scheduler/MessageScheduler.java deleted file mode 100644 index 472c493..0000000 --- a/src/main/java/dev/vality/hooker/scheduler/MessageScheduler.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.vality.hooker.scheduler; - -import dev.vality.hooker.model.Message; -import dev.vality.hooker.model.Queue; -import dev.vality.hooker.service.MessageProcessor; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; - -import javax.annotation.PostConstruct; - -import java.util.stream.IntStream; - -@Slf4j -@RequiredArgsConstructor -public class MessageScheduler { - private final int threadPoolSize; - private final int delayMillis; - private final MessageProcessor messageProcessor; - private final ThreadPoolTaskScheduler executorService; - - @PostConstruct - public void init() { - IntStream.range(0, threadPoolSize).forEach(i -> - executorService.scheduleWithFixedDelay(messageProcessor, delayMillis)); - } -} diff --git a/src/main/java/dev/vality/hooker/scheduler/MessageSender.java b/src/main/java/dev/vality/hooker/scheduler/MessageSender.java deleted file mode 100644 index 1344705..0000000 --- a/src/main/java/dev/vality/hooker/scheduler/MessageSender.java +++ /dev/null @@ -1,77 +0,0 @@ -package dev.vality.hooker.scheduler; - -import com.fasterxml.jackson.databind.ObjectMapper; -import dev.vality.hooker.model.Message; -import dev.vality.hooker.model.Queue; -import dev.vality.hooker.model.QueueStatus; -import dev.vality.hooker.model.Task; -import dev.vality.hooker.service.EventService; -import dev.vality.hooker.service.FaultDetectorService; -import dev.vality.hooker.service.PostSender; -import dev.vality.hooker.service.crypt.Signer; -import dev.vality.hooker.service.err.PostRequestException; -import dev.vality.swag_webhook_events.model.Event; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.http.HttpStatus; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -@Slf4j -@RequiredArgsConstructor -public class MessageSender { - private final int connectionPoolSize; - private final int timeout; - private final Signer signer; - private final EventService eventService; - private final ObjectMapper objectMapper; - private final FaultDetectorService faultDetector; - - public List send(Map > scheduledTasks, Map queuesMap, - Map messagesMap) { - PostSender postSender = new PostSender(connectionPoolSize, timeout); - List queueStatuses = new ArrayList<>(); - for (Map.Entry > entry : scheduledTasks.entrySet()) { - Long queueId = entry.getKey(); - List tasks = entry.getValue(); - Q queue = queuesMap.get(queueId); - QueueStatus queueStatus = new QueueStatus(); - queueStatus.setQueue(queue); - M currentMessage = null; - try { - for (Task task : tasks) { - long messageId = task.getMessageId(); - M message = messagesMap.get(messageId); - currentMessage = message; - Event event = eventService.getEventByMessage(message); - final String messageJson = objectMapper.writeValueAsString(event); - final String signature = signer.sign(messageJson, queue.getHook().getPrivKey()); - faultDetector.startRequest(queue.getHook().getId(), message.getEventId()); - int statusCode = - postSender.doPost(queue.getHook().getUrl(), message.getId(), messageJson, signature); - if (statusCode != HttpStatus.SC_OK) { - String wrongCodeMessage = String.format( - "Wrong status code: %d from merchant, we'll try to resend it. Message with id: %d %s", - statusCode, message.getId(), message); - log.info(wrongCodeMessage); - faultDetector.errorRequest(queue.getHook().getId(), message.getEventId()); - throw new PostRequestException(wrongCodeMessage); - } - faultDetector.finishRequest(queue.getHook().getId(), message.getEventId()); - queueStatus.getMessagesDone().add(message.getId()); - } - queueStatus.setSuccess(true); - } catch (Exception e) { - if (currentMessage != null) { - log.warn("Couldn't send message with id {} {} to hook {}. We'll try to resend it", - currentMessage.getId(), currentMessage, queue.getHook(), e); - } - queueStatus.setSuccess(false); - } - queueStatuses.add(queueStatus); - } - return queueStatuses; - } -} diff --git a/src/main/java/dev/vality/hooker/service/AdditionalHeadersGenerator.java b/src/main/java/dev/vality/hooker/service/AdditionalHeadersGenerator.java new file mode 100644 index 0000000..e74f1a9 --- /dev/null +++ b/src/main/java/dev/vality/hooker/service/AdditionalHeadersGenerator.java @@ -0,0 +1,16 @@ +package dev.vality.hooker.service; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Service +@RequiredArgsConstructor +public class AdditionalHeadersGenerator { + public static final String SIGNATURE_HEADER = "Content-Signature"; + + public Map generate(String signature) { + return Map.of(SIGNATURE_HEADER, "alg=RS256; digest=" + signature); + } +} diff --git a/src/main/java/dev/vality/hooker/service/BatchService.java b/src/main/java/dev/vality/hooker/service/BatchService.java deleted file mode 100644 index df71059..0000000 --- a/src/main/java/dev/vality/hooker/service/BatchService.java +++ /dev/null @@ -1,42 +0,0 @@ -package dev.vality.hooker.service; - -import dev.vality.hooker.dao.impl.InvoicingMessageDaoImpl; -import dev.vality.hooker.dao.impl.InvoicingQueueDao; -import dev.vality.hooker.dao.impl.InvoicingTaskDao; -import dev.vality.hooker.dao.impl.MessageIdsGeneratorDaoImpl; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.Message; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.stream.Collectors; - -@Service -@Slf4j -@RequiredArgsConstructor -public class BatchService { - - private final InvoicingMessageDaoImpl invoicingMessageDao; - private final InvoicingQueueDao invoicingQueueDao; - private final InvoicingTaskDao invoicingTaskDao; - private final MessageIdsGeneratorDaoImpl messageIdsGeneratorDao; - - public void process(List messages) { - log.info("Start processing of batch, size={}", messages.size()); - List ids = messageIdsGeneratorDao.get(messages.size()); - List eventIds = messageIdsGeneratorDao.get(messages.size()); - for (int i = 0; i < messages.size(); ++i) { - messages.get(i).setId(ids.get(i)); - messages.get(i).setEventId(eventIds.get(i)); - } - invoicingMessageDao.saveBatch(messages); - List messageIds = messages.stream().map(Message::getId).collect(Collectors.toList()); - int[] queueBatchResult = invoicingQueueDao.saveBatchWithPolicies(messageIds); - log.info("Queue batch size={}", queueBatchResult.length); - int taskInsertResult = invoicingTaskDao.save(messageIds); - log.info("Task insert size={}", taskInsertResult); - log.info("End processing of batch"); - } -} diff --git a/src/main/java/dev/vality/hooker/service/CustomerEventService.java b/src/main/java/dev/vality/hooker/service/CustomerEventService.java index c19f0fc..e546db1 100644 --- a/src/main/java/dev/vality/hooker/service/CustomerEventService.java +++ b/src/main/java/dev/vality/hooker/service/CustomerEventService.java @@ -12,13 +12,7 @@ import dev.vality.hooker.exception.RemoteHostException; import dev.vality.hooker.model.CustomerMessage; import dev.vality.hooker.utils.HellgateUtils; import dev.vality.hooker.utils.TimeUtils; -import dev.vality.swag_webhook_events.model.CustomerBindingFailed; -import dev.vality.swag_webhook_events.model.CustomerBindingStarted; -import dev.vality.swag_webhook_events.model.CustomerBindingSucceeded; -import dev.vality.swag_webhook_events.model.CustomerCreated; -import dev.vality.swag_webhook_events.model.CustomerDeleted; -import dev.vality.swag_webhook_events.model.CustomerReady; -import dev.vality.swag_webhook_events.model.Event; +import dev.vality.swag_webhook_events.model.*; import dev.vality.woody.api.flow.WFlow; import dev.vality.woody.api.trace.ContextUtils; import lombok.RequiredArgsConstructor; @@ -38,17 +32,17 @@ public class CustomerEventService implements EventService { try { Customer customer = woodyFlow.createServiceFork(() -> { addWoodyContext(); - return customerClient.get(message.getCustomerId(), + return customerClient.get(message.getSourceId(), HellgateUtils.getEventRange(message.getSequenceId().intValue())); } ).call(); return resolveEvent(message, customer) - .eventID(message.getEventId().intValue()) + .eventID(message.getId().intValue()) .occuredAt(TimeUtils.toOffsetDateTime(message.getEventTime())) .topic(Event.TopicEnum.CUSTOMERSTOPIC); } catch (CustomerNotFound e) { - throw new NotFoundException("Customer not found, invoiceId=" + message.getCustomerId()); + throw new NotFoundException("Customer not found, invoiceId=" + message.getSourceId()); } catch (Exception e) { throw new RemoteHostException(e); } @@ -87,12 +81,12 @@ public class CustomerEventService implements EventService { } private dev.vality.damsel.payment_processing.CustomerBinding extractBinding(CustomerMessage message, - Customer customer) { + Customer customer) { return customer.getBindings().stream() .filter(b -> b.getId().equals(message.getBindingId())) .findFirst() .orElseThrow(() -> new NotFoundException(String.format("Customer binding not found, customerId=%s, bindingId=%s", - message.getCustomerId(), message.getBindingId()))); + message.getSourceId(), message.getBindingId()))); } } diff --git a/src/main/java/dev/vality/hooker/service/CustomerLastEventService.java b/src/main/java/dev/vality/hooker/service/CustomerLastEventService.java deleted file mode 100644 index e23df4a..0000000 --- a/src/main/java/dev/vality/hooker/service/CustomerLastEventService.java +++ /dev/null @@ -1,20 +0,0 @@ -package dev.vality.hooker.service; - -import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -@RequiredArgsConstructor -public class CustomerLastEventService { - - private final CustomerDaoImpl customerDao; - - public Long getLastEventId() { - Long custLastEventId = customerDao.getMaxEventId(); - log.info("Get last event id = {}", custLastEventId); - return custLastEventId; - } -} diff --git a/src/main/java/dev/vality/hooker/service/FaultDetectorService.java b/src/main/java/dev/vality/hooker/service/FaultDetectorService.java deleted file mode 100644 index 1639f7c..0000000 --- a/src/main/java/dev/vality/hooker/service/FaultDetectorService.java +++ /dev/null @@ -1,13 +0,0 @@ -package dev.vality.hooker.service; - -public interface FaultDetectorService { - - double getRate(long hookId); - - void startRequest(long hookId, long eventId); - - void finishRequest(long hookId, long eventId); - - void errorRequest(long hookId, long eventId); - -} diff --git a/src/main/java/dev/vality/hooker/service/FaultDetectorServiceImpl.java b/src/main/java/dev/vality/hooker/service/FaultDetectorServiceImpl.java deleted file mode 100644 index 4e6baf6..0000000 --- a/src/main/java/dev/vality/hooker/service/FaultDetectorServiceImpl.java +++ /dev/null @@ -1,89 +0,0 @@ -package dev.vality.hooker.service; - -import dev.vality.damsel.fault_detector.Error; -import dev.vality.damsel.fault_detector.FaultDetectorSrv; -import dev.vality.damsel.fault_detector.Finish; -import dev.vality.damsel.fault_detector.Operation; -import dev.vality.damsel.fault_detector.OperationState; -import dev.vality.damsel.fault_detector.ServiceConfig; -import dev.vality.damsel.fault_detector.ServiceStatistics; -import dev.vality.damsel.fault_detector.Start; -import dev.vality.geck.common.util.TypeUtil; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; - -import javax.annotation.PostConstruct; - -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.List; - -@Slf4j -@Service -@RequiredArgsConstructor -public class FaultDetectorServiceImpl implements FaultDetectorService { - - private final FaultDetectorSrv.Iface faultDetector; - - @Value("${service.fault-detector.slidingWindow}") - private Long slidingWindowMillis; - - @Value("${service.fault-detector.operationTimeLimit}") - private Long operationTimeLimit; - - private ServiceConfig serviceConfig; - - @PostConstruct - public void init() { - serviceConfig = new ServiceConfig() - .setSlidingWindow(slidingWindowMillis) - .setOperationTimeLimit(operationTimeLimit); - } - - @Override - public double getRate(long hookId) { - try { - List statistics = faultDetector.getStatistics(List.of(buildServiceId(hookId))); - return statistics.isEmpty() ? 0 : statistics.get(0).getFailureRate(); - } catch (Exception e) { - log.error("Error in FaultDetectorService when getStatistics", e); - return 0; - } - } - - @Override - public void startRequest(long hookId, long eventId) { - registerOperation(hookId, eventId, OperationState.start(new Start(getNow()))); - } - - @Override - public void finishRequest(long hookId, long eventId) { - registerOperation(hookId, eventId, OperationState.finish(new Finish(getNow()))); - } - - @Override - public void errorRequest(long hookId, long eventId) { - registerOperation(hookId, eventId, OperationState.error(new Error(getNow()))); - } - - private void registerOperation(long hookId, long eventId, OperationState operationState) { - Operation operation = new Operation() - .setOperationId(String.valueOf(eventId)) - .setState(operationState); - try { - faultDetector.registerOperation(buildServiceId(hookId), operation, serviceConfig); - } catch (Exception e) { - log.error("Error in FaultDetectorService when registerOperation", e); - } - } - - private String getNow() { - return TypeUtil.temporalToString(LocalDateTime.now(ZoneOffset.UTC)); - } - - private String buildServiceId(long id) { - return "hooker-" + id; - } -} diff --git a/src/main/java/dev/vality/hooker/service/HandlerManager.java b/src/main/java/dev/vality/hooker/service/HandlerManager.java index b711830..9f13d45 100644 --- a/src/main/java/dev/vality/hooker/service/HandlerManager.java +++ b/src/main/java/dev/vality/hooker/service/HandlerManager.java @@ -1,7 +1,8 @@ package dev.vality.hooker.service; import dev.vality.damsel.payment_processing.InvoiceChange; -import dev.vality.hooker.handler.poller.invoicing.AbstractInvoiceEventMapper; +import dev.vality.hooker.handler.Mapper; +import dev.vality.hooker.model.InvoicingMessage; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -12,9 +13,9 @@ import java.util.Optional; @RequiredArgsConstructor public class HandlerManager { - private final List handlers; + private final List > handlers; - public Optional getHandler(InvoiceChange change) { + public Optional > getHandler(InvoiceChange change) { return handlers.stream().filter(handler -> handler.accept(change)).findFirst(); } } \ No newline at end of file diff --git a/src/main/java/dev/vality/hooker/service/InvoicingEventService.java b/src/main/java/dev/vality/hooker/service/InvoicingEventService.java index ee58419..71b3731 100644 --- a/src/main/java/dev/vality/hooker/service/InvoicingEventService.java +++ b/src/main/java/dev/vality/hooker/service/InvoicingEventService.java @@ -11,23 +11,7 @@ import dev.vality.hooker.exception.RemoteHostException; import dev.vality.hooker.model.InvoicingMessage; import dev.vality.hooker.utils.HellgateUtils; import dev.vality.hooker.utils.TimeUtils; -import dev.vality.swag_webhook_events.model.Event; -import dev.vality.swag_webhook_events.model.Invoice; -import dev.vality.swag_webhook_events.model.InvoiceCancelled; -import dev.vality.swag_webhook_events.model.InvoiceCreated; -import dev.vality.swag_webhook_events.model.InvoiceFulfilled; -import dev.vality.swag_webhook_events.model.InvoicePaid; -import dev.vality.swag_webhook_events.model.Payment; -import dev.vality.swag_webhook_events.model.PaymentCancelled; -import dev.vality.swag_webhook_events.model.PaymentCaptured; -import dev.vality.swag_webhook_events.model.PaymentFailed; -import dev.vality.swag_webhook_events.model.PaymentProcessed; -import dev.vality.swag_webhook_events.model.PaymentRefunded; -import dev.vality.swag_webhook_events.model.PaymentStarted; -import dev.vality.swag_webhook_events.model.Refund; -import dev.vality.swag_webhook_events.model.RefundCreated; -import dev.vality.swag_webhook_events.model.RefundFailed; -import dev.vality.swag_webhook_events.model.RefundSucceeded; +import dev.vality.swag_webhook_events.model.*; import lombok.RequiredArgsConstructor; import org.apache.thrift.TException; import org.springframework.stereotype.Service; @@ -45,7 +29,7 @@ public class InvoicingEventService @Override public Event getEventByMessage(InvoicingMessage message) { return resolveEvent(message, getInvoiceByMessage(message)) - .eventID(message.getEventId().intValue()) + .eventID(message.getId().intValue()) .occuredAt(TimeUtils.toOffsetDateTime(message.getEventTime())) .topic(Event.TopicEnum.INVOICESTOPIC); } @@ -60,41 +44,34 @@ public class InvoicingEventService try { return invoicingClient.get( HellgateUtils.USER_INFO, - message.getInvoiceId(), + message.getSourceId(), HellgateUtils.getEventRange(message.getSequenceId().intValue()) ); } catch (InvoiceNotFound e) { - throw new NotFoundException("Invoice not found, invoiceId=" + message.getInvoiceId()); + throw new NotFoundException("Invoice not found, invoiceId=" + message.getSourceId()); } catch (TException e) { throw new RemoteHostException(e); } } private Event resolveEvent(InvoicingMessage m, dev.vality.damsel.payment_processing.Invoice invoiceInfo) { - switch (m.getEventType()) { - case INVOICE_CREATED: - return new InvoiceCreated() - .invoice(getSwagInvoice(invoiceInfo)) - .eventType(Event.EventTypeEnum.INVOICECREATED); - case INVOICE_STATUS_CHANGED: - return resolveInvoiceStatusChanged(m, invoiceInfo); - case INVOICE_PAYMENT_STARTED: - return new PaymentStarted() - .invoice(getSwagInvoice(invoiceInfo)) - .payment(getSwagPayment(m, invoiceInfo)) - .eventType(Event.EventTypeEnum.PAYMENTSTARTED); - case INVOICE_PAYMENT_STATUS_CHANGED: - return resolvePaymentStatusChanged(m, invoiceInfo); - case INVOICE_PAYMENT_REFUND_STARTED: - return new RefundCreated() - .invoice(getSwagInvoice(invoiceInfo)) - .payment(getSwagPayment(m, invoiceInfo)) - .refund(getSwagRefund(m, invoiceInfo)); - case INVOICE_PAYMENT_REFUND_STATUS_CHANGED: - return resolveRefundStatusChanged(m, invoiceInfo); - default: - throw new UnsupportedOperationException("Unknown event type " + m.getEventType()); - } + return switch (m.getEventType()) { + case INVOICE_CREATED -> new InvoiceCreated() + .invoice(getSwagInvoice(invoiceInfo)) + .eventType(Event.EventTypeEnum.INVOICECREATED); + case INVOICE_STATUS_CHANGED -> resolveInvoiceStatusChanged(m, invoiceInfo); + case INVOICE_PAYMENT_STARTED -> new PaymentStarted() + .invoice(getSwagInvoice(invoiceInfo)) + .payment(getSwagPayment(m, invoiceInfo)) + .eventType(Event.EventTypeEnum.PAYMENTSTARTED); + case INVOICE_PAYMENT_STATUS_CHANGED -> resolvePaymentStatusChanged(m, invoiceInfo); + case INVOICE_PAYMENT_REFUND_STARTED -> new RefundCreated() + .invoice(getSwagInvoice(invoiceInfo)) + .payment(getSwagPayment(m, invoiceInfo)) + .refund(getSwagRefund(m, invoiceInfo)); + case INVOICE_PAYMENT_REFUND_STATUS_CHANGED -> resolveRefundStatusChanged(m, invoiceInfo); + default -> throw new UnsupportedOperationException("Unknown event type " + m.getEventType()); + }; } private Invoice getSwagInvoice(dev.vality.damsel.payment_processing.Invoice invoiceInfo) { @@ -134,7 +111,7 @@ public class InvoicingEventService .findFirst() .orElseThrow( () -> new NotFoundException( - String.format("Payment not found, invoiceId=%s, paymentId=%s", message.getInvoiceId(), + String.format("Payment not found, invoiceId=%s, paymentId=%s", message.getSourceId(), message.getPaymentId()) ) ); @@ -194,7 +171,7 @@ public class InvoicingEventService () -> new NotFoundException( String.format( "Refund not found, invoiceId=%s, paymentId=%s, refundId=%s", - m.getInvoiceId(), m.getPaymentId(), m.getRefundId() + m.getSourceId(), m.getPaymentId(), m.getRefundId() ) ) ); @@ -205,15 +182,11 @@ public class InvoicingEventService Invoice swagInvoice = getSwagInvoice(invoiceInfo); Payment swagPayment = getSwagPayment(message, invoiceInfo); Refund swagRefund = getSwagRefund(message, invoiceInfo); - switch (message.getRefundStatus()) { - case PENDING: - return new RefundCreated().invoice(swagInvoice).payment(swagPayment).refund(swagRefund); - case SUCCEEDED: - return new RefundSucceeded().invoice(swagInvoice).payment(swagPayment).refund(swagRefund); - case FAILED: - return new RefundFailed().invoice(swagInvoice).payment(swagPayment).refund(swagRefund); - default: - throw new UnsupportedOperationException("Unknown refund status " + message.getRefundStatus()); - } + return switch (message.getRefundStatus()) { + case PENDING -> new RefundCreated().invoice(swagInvoice).payment(swagPayment).refund(swagRefund); + case SUCCEEDED -> new RefundSucceeded().invoice(swagInvoice).payment(swagPayment).refund(swagRefund); + case FAILED -> new RefundFailed().invoice(swagInvoice).payment(swagPayment).refund(swagRefund); + default -> throw new UnsupportedOperationException("Unknown refund status " + message.getRefundStatus()); + }; } } diff --git a/src/main/java/dev/vality/hooker/service/MessageProcessor.java b/src/main/java/dev/vality/hooker/service/MessageProcessor.java deleted file mode 100644 index 335aa98..0000000 --- a/src/main/java/dev/vality/hooker/service/MessageProcessor.java +++ /dev/null @@ -1,118 +0,0 @@ -package dev.vality.hooker.service; - -import dev.vality.hooker.dao.HookDao; -import dev.vality.hooker.dao.MessageDao; -import dev.vality.hooker.dao.QueueDao; -import dev.vality.hooker.dao.TaskDao; -import dev.vality.hooker.exception.DaoException; -import dev.vality.hooker.model.Message; -import dev.vality.hooker.model.Queue; -import dev.vality.hooker.model.QueueStatus; -import dev.vality.hooker.model.Task; -import dev.vality.hooker.retry.RetryPoliciesService; -import dev.vality.hooker.retry.RetryPolicy; -import dev.vality.hooker.retry.RetryPolicyRecord; -import dev.vality.hooker.scheduler.MessageSender; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.transaction.support.TransactionTemplate; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -@Slf4j -@RequiredArgsConstructor -public class MessageProcessor implements Runnable { - - private static final double UPDATE_PROBABILITY = 0.25; - private final HookDao hookDao; - private final TaskDao taskDao; - private final QueueDao queueDao; - private final MessageDaomessageDao; - private final RetryPoliciesService retryPoliciesService; - private final TransactionTemplate transactionTemplate; - private final FaultDetectorService faultDetector; - private final MessageSender messageSender; - - @Override - public void run() { - transactionTemplate.execute(k -> { - process(); - return null; - }); - } - - private void process() { - Map > scheduledTasks = taskDao.getScheduled(); - log.debug("scheduledTasks {}", scheduledTasks); - if (scheduledTasks.entrySet().isEmpty()) { - return; - } - - Set queueIds = scheduledTasks.keySet(); - Map queuesMap = - queueDao.getWithPolicies(queueIds).stream().collect(Collectors.toMap(Queue::getId, q -> q)); - Set messageIds = scheduledTasks.values().stream().flatMap(Collection::stream).map(Task::getMessageId) - .collect(Collectors.toSet()); - Map messagesMap = - messageDao.getBy(messageIds).stream().collect(Collectors.toMap(Message::getId, m -> m)); - - List queueStatuses = messageSender.send(scheduledTasks, queuesMap, messagesMap); - queueStatuses.forEach(queueStatus -> { - try { - Queue queue = queueStatus.getQueue(); - queueStatus.getMessagesDone().forEach(id -> taskDao.remove(queue.getId(), id)); - if (queueStatus.isSuccess()) { - done(queue); - } else { - fail(queue); - } - } catch (DaoException e) { - log.error("DaoException error when remove sent messages. " + - "It's not a big deal, but some messages may be re-sent: {}", - queueStatus.getMessagesDone(), e); - } - }); - } - - private void done(Queue queue) { - if (queue.getRetryPolicyRecord().isFailed()) { - RetryPolicyRecord record = queue.getRetryPolicyRecord(); - record.reset(); - updatePolicy(record); - updateAvailability(queue); - } else { - if (Math.random() < UPDATE_PROBABILITY) { - updateAvailability(queue); - } - } - } - - private void fail(Queue queue) { - log.warn("Queue {} failed.", queue.getId()); - RetryPolicy retryPolicy = retryPoliciesService.getRetryPolicyByType(queue.getHook().getRetryPolicyType()); - RetryPolicyRecord retryPolicyRecord = queue.getRetryPolicyRecord(); - retryPolicy.updateFailed(retryPolicyRecord); - updatePolicy(retryPolicyRecord); - updateAvailability(queue); - if (retryPolicy.shouldDisable(retryPolicyRecord)) { - queueDao.disable(queue.getId()); - taskDao.removeAll(queue.getId()); - log.warn("Queue {} was disabled according to retry policy.", queue.getId()); - } - } - - private void updatePolicy(RetryPolicyRecord record) { - retryPoliciesService.update(record); - log.info("Queue retry policy has been updated {}", record); - } - - private void updateAvailability(Queue queue) { - //double rate = faultDetector.getRate(queue.getHook().getId()); - //hookDao.updateAvailability(queue.getHook().getId(), rate); - //log.info("Hook {} availability has been updated to {}", queue.getHook().getId(), rate); - } -} diff --git a/src/main/java/dev/vality/hooker/service/MessageService.java b/src/main/java/dev/vality/hooker/service/MessageService.java new file mode 100644 index 0000000..3c853df --- /dev/null +++ b/src/main/java/dev/vality/hooker/service/MessageService.java @@ -0,0 +1,41 @@ +package dev.vality.hooker.service; + +import dev.vality.hooker.converter.WebhookMessageBuilder; +import dev.vality.hooker.dao.MessageDao; +import dev.vality.hooker.model.Message; +import dev.vality.swag_webhook_events.model.Event; +import dev.vality.webhook.dispatcher.WebhookMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@RequiredArgsConstructor +public class MessageService { + private final MessageDao messageDao; + private final EventService eventService; + private final WebhookMessageBuilder webhookMessageBuilder; + private final WebhookKafkaProducerService webhookKafkaProducerService; + + public void process(T message) { + log.info("Start processing of message {}", message); + Long id = messageDao.save(message); + String sourceId = message.getSourceId(); + if (id != null) { + message.setId(id); + var webhookModels = messageDao.getWebhookModels(id); + if (!webhookModels.isEmpty()) { + log.info("Processing {} webhook(s)", webhookModels.size()); + Event event = eventService.getEventByMessage(message); + webhookModels.forEach(w -> { + Long hookId = w.getHookId(); + Long parentEventId = messageDao.getParentId(hookId, sourceId, id); + WebhookMessage webhookMessage = webhookMessageBuilder.build(w, event, sourceId, parentEventId); + log.info("Try to send webhook to kafka: {}", webhookMessage); + webhookKafkaProducerService.send(webhookMessage); + log.info("Webhook to kafka was sent: sourceId={}", webhookMessage.getSourceId()); + }); + } + } + log.info("End processing of message {}", sourceId); + } +} diff --git a/src/main/java/dev/vality/hooker/service/PostSender.java b/src/main/java/dev/vality/hooker/service/PostSender.java deleted file mode 100644 index bbbe910..0000000 --- a/src/main/java/dev/vality/hooker/service/PostSender.java +++ /dev/null @@ -1,57 +0,0 @@ -package dev.vality.hooker.service; - -import dev.vality.hooker.logging.HttpLoggingInterceptor; -import lombok.extern.slf4j.Slf4j; -import okhttp3.ConnectionPool; -import okhttp3.MediaType; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.RequestBody; -import okhttp3.Response; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -@Slf4j -public class PostSender { - - public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); - public static final String SIGNATURE_HEADER = "Content-Signature"; - public static final long RESPONSE_MAX_LENGTH = 4096L; - private final OkHttpClient httpClient; - - public PostSender(int connectionPoolSize, int timeout) { - OkHttpClient.Builder httpBuilder = new OkHttpClient.Builder(); - - if (log.isDebugEnabled()) { - HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(message -> log.debug(message)); - httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); - httpBuilder.addInterceptor(httpLoggingInterceptor); - } - - ConnectionPool connectionPool = new ConnectionPool(2 * connectionPoolSize, 5, TimeUnit.MINUTES); - this.httpClient = httpBuilder - .connectionPool(connectionPool) - .retryOnConnectionFailure(false) - .connectTimeout(timeout, TimeUnit.SECONDS) - .writeTimeout(timeout, TimeUnit.SECONDS) - .readTimeout(timeout, TimeUnit.SECONDS) - .build(); - } - - public int doPost(String url, long messageId, String paramsAsString, String signature) throws IOException { - log.info("Sending message with id {}, {} to hook: {} ", messageId, paramsAsString, url); - RequestBody body = RequestBody.create(JSON, paramsAsString); - final Request request = new Request.Builder() - .url(url) - .addHeader(SIGNATURE_HEADER, "alg=RS256; digest=" + signature) - .post(body) - .build(); - - try (Response response = httpClient.newCall(request).execute()) { - log.info("Response from hook: messageId: {}, code: {}; body: {}", messageId, response.code(), - response.body() != null ? response.peekBody(RESPONSE_MAX_LENGTH).string() : " "); - return response.code(); - } - } -} diff --git a/src/main/java/dev/vality/hooker/service/WebhookKafkaProducerService.java b/src/main/java/dev/vality/hooker/service/WebhookKafkaProducerService.java new file mode 100644 index 0000000..f2b2dd8 --- /dev/null +++ b/src/main/java/dev/vality/hooker/service/WebhookKafkaProducerService.java @@ -0,0 +1,42 @@ +package dev.vality.hooker.service; + +import dev.vality.kafka.common.exception.KafkaProduceException; +import dev.vality.webhook.dispatcher.WebhookMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class WebhookKafkaProducerService { + + private final KafkaTemplate kafkaTemplate; + + @Value("${kafka.topic.webhook-dispatcher.name}") + private String topicName; + + @Value("${kafka.topic.webhook-dispatcher.produce.enabled}") + private boolean producerEnabled; + + public void send(WebhookMessage webhookMessage) { + if (producerEnabled) { + sendWebhook(webhookMessage); + } + } + + private void sendWebhook(WebhookMessage webhookMessage) { + try { + kafkaTemplate.send(topicName, webhookMessage.getSourceId(), webhookMessage).get(); + } catch (InterruptedException e) { + log.error("InterruptedException command: {}", webhookMessage, e); + Thread.currentThread().interrupt(); + throw new KafkaProduceException(e); + } catch (Exception e) { + log.error("Error while sending command: {}", webhookMessage, e); + throw new KafkaProduceException(e); + } + } +} diff --git a/src/main/java/dev/vality/hooker/service/WebhookManager.java b/src/main/java/dev/vality/hooker/service/WebhookManager.java index ee7a71c..74cc22b 100644 --- a/src/main/java/dev/vality/hooker/service/WebhookManager.java +++ b/src/main/java/dev/vality/hooker/service/WebhookManager.java @@ -1,10 +1,6 @@ package dev.vality.hooker.service; -import dev.vality.damsel.webhooker.LimitExceeded; -import dev.vality.damsel.webhooker.Webhook; -import dev.vality.damsel.webhooker.WebhookManagerSrv; -import dev.vality.damsel.webhooker.WebhookNotFound; -import dev.vality.damsel.webhooker.WebhookParams; +import dev.vality.damsel.webhooker.*; import dev.vality.hooker.dao.HookDao; import dev.vality.hooker.model.Hook; import dev.vality.hooker.utils.HookConverter; diff --git a/src/main/java/dev/vality/hooker/service/WebhookMessageService.java b/src/main/java/dev/vality/hooker/service/WebhookMessageService.java deleted file mode 100644 index 2a65149..0000000 --- a/src/main/java/dev/vality/hooker/service/WebhookMessageService.java +++ /dev/null @@ -1,47 +0,0 @@ -package dev.vality.hooker.service; - -import dev.vality.damsel.webhooker.SourceNotFound; -import dev.vality.damsel.webhooker.WebhookMessageServiceSrv; -import dev.vality.damsel.webhooker.WebhookNotFound; -import dev.vality.hooker.dao.HookDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; -import dev.vality.hooker.dao.impl.InvoicingTaskDao; -import dev.vality.hooker.model.Hook; -import dev.vality.swag_webhook_events.model.Event; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.apache.thrift.TException; -import org.springframework.stereotype.Service; - -@Service -@Slf4j -@RequiredArgsConstructor -public class WebhookMessageService implements WebhookMessageServiceSrv.Iface { - - private final HookDao hookDao; - private final InvoicingTaskDao invoicingTaskDao; - private final CustomerTaskDao customerTaskDao; - - @Override - public void send(long hookId, String sourceId) throws TException { - log.info("Start creating tasks for sending hooks for hookId={}, invoiceId={}", hookId, sourceId); - Hook hook = hookDao.getHookById(hookId); - if (hook == null) { - log.warn("Webhook with id={} not found", hookId); - throw new WebhookNotFound(); - } - int count; - if (hook.getTopic().equals(Event.TopicEnum.INVOICESTOPIC.getValue())) { - count = invoicingTaskDao.save(hookId, sourceId); - } else if (hook.getTopic().equals(Event.TopicEnum.CUSTOMERSTOPIC.getValue())) { - count = customerTaskDao.create(hookId, sourceId); - } else { - throw new RuntimeException("Unknown webhook type " + hook.getTopic()); - } - if (count < 1) { - log.warn("No tasks created for hookId={} and invoiceId={}", hookId, sourceId); - throw new SourceNotFound(); - } - log.info("Tasks has been created. Count={} for hookId={}, invoiceId={}", count, hookId, sourceId); - } -} diff --git a/src/main/java/dev/vality/hooker/service/crypt/AsymSigner.java b/src/main/java/dev/vality/hooker/service/crypt/AsymSigner.java index a9f656a..2946748 100644 --- a/src/main/java/dev/vality/hooker/service/crypt/AsymSigner.java +++ b/src/main/java/dev/vality/hooker/service/crypt/AsymSigner.java @@ -4,13 +4,7 @@ import dev.vality.hooker.service.err.UnknownCryptoException; import org.springframework.stereotype.Component; import java.nio.charset.StandardCharsets; -import java.security.InvalidKeyException; -import java.security.KeyFactory; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.Signature; -import java.security.SignatureException; +import java.security.*; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; diff --git a/src/main/java/dev/vality/hooker/service/err/PostRequestException.java b/src/main/java/dev/vality/hooker/service/err/PostRequestException.java deleted file mode 100644 index f0af6c0..0000000 --- a/src/main/java/dev/vality/hooker/service/err/PostRequestException.java +++ /dev/null @@ -1,17 +0,0 @@ -package dev.vality.hooker.service.err; - -public class PostRequestException extends Exception { - public PostRequestException(Throwable cause) { - super(cause); - } - - public PostRequestException(String errMessage) { - super(errMessage); - } - - @Override - public String getMessage() { - String message = getCause() != null ? getCause().getMessage() : super.getMessage(); - return "Unknown error during request to merchant execution. \n" + message; - } -} diff --git a/src/main/java/dev/vality/hooker/utils/EventFilterUtils.java b/src/main/java/dev/vality/hooker/utils/EventFilterUtils.java index b283a4a..88445ce 100644 --- a/src/main/java/dev/vality/hooker/utils/EventFilterUtils.java +++ b/src/main/java/dev/vality/hooker/utils/EventFilterUtils.java @@ -1,28 +1,6 @@ package dev.vality.hooker.utils; -import dev.vality.damsel.webhooker.CustomerBindingEvent; -import dev.vality.damsel.webhooker.CustomerBindingFailed; -import dev.vality.damsel.webhooker.CustomerBindingStarted; -import dev.vality.damsel.webhooker.CustomerBindingSucceeded; -import dev.vality.damsel.webhooker.CustomerCreated; -import dev.vality.damsel.webhooker.CustomerDeleted; -import dev.vality.damsel.webhooker.CustomerEventFilter; -import dev.vality.damsel.webhooker.CustomerEventType; -import dev.vality.damsel.webhooker.CustomerStatusReady; -import dev.vality.damsel.webhooker.EventFilter; -import dev.vality.damsel.webhooker.InvoiceCreated; -import dev.vality.damsel.webhooker.InvoiceEventFilter; -import dev.vality.damsel.webhooker.InvoiceEventType; -import dev.vality.damsel.webhooker.InvoicePaymentCreated; -import dev.vality.damsel.webhooker.InvoicePaymentEventType; -import dev.vality.damsel.webhooker.InvoicePaymentRefundChange; -import dev.vality.damsel.webhooker.InvoicePaymentRefundCreated; -import dev.vality.damsel.webhooker.InvoicePaymentRefundStatus; -import dev.vality.damsel.webhooker.InvoicePaymentRefundStatusChanged; -import dev.vality.damsel.webhooker.InvoicePaymentStatus; -import dev.vality.damsel.webhooker.InvoicePaymentStatusChanged; -import dev.vality.damsel.webhooker.InvoiceStatus; -import dev.vality.damsel.webhooker.InvoiceStatusChanged; +import dev.vality.damsel.webhooker.*; import dev.vality.hooker.dao.WebhookAdditionalFilter; import dev.vality.hooker.model.EventType; import dev.vality.swag_webhook_events.model.Event; diff --git a/src/main/java/dev/vality/hooker/utils/KeyUtils.java b/src/main/java/dev/vality/hooker/utils/KeyUtils.java index 836e12e..b985903 100644 --- a/src/main/java/dev/vality/hooker/utils/KeyUtils.java +++ b/src/main/java/dev/vality/hooker/utils/KeyUtils.java @@ -7,7 +7,7 @@ public class KeyUtils { public static InvoicingMessageKey key(InvoicingMessage message) { return InvoicingMessageKey.builder() - .invoiceId(message.getInvoiceId()) + .invoiceId(message.getSourceId()) .paymentId(message.getPaymentId()) .refundId(message.getRefundId()) .type(message.getType()) diff --git a/src/main/java/dev/vality/hooker/utils/PaymentToolUtils.java b/src/main/java/dev/vality/hooker/utils/PaymentToolUtils.java index caf2e67..37485e8 100644 --- a/src/main/java/dev/vality/hooker/utils/PaymentToolUtils.java +++ b/src/main/java/dev/vality/hooker/utils/PaymentToolUtils.java @@ -11,8 +11,6 @@ import dev.vality.swag_webhook_events.model.*; import java.nio.charset.StandardCharsets; import java.util.Base64; -import java.util.Objects; -import java.util.Optional; public class PaymentToolUtils { @@ -25,14 +23,14 @@ public class PaymentToolUtils { .lastDigits(paymentTool.getBankCard().getLastDigits()) .cardNumberMask( paymentTool.getBankCard().getBin() + "******" + paymentTool.getBankCard().getLastDigits()) - .tokenProvider( - Optional.ofNullable(TokenProviderUtil.getTokenProviderName(paymentTool.getBankCard())) - .map(PaymentToolDetailsBankCard.TokenProviderEnum::fromValue) - .orElse(null) - ) + .tokenProvider(paymentTool.getBankCard().getTokenProviderDeprecated() != null + ? PaymentToolDetailsBankCard.TokenProviderEnum.fromValue( + paymentTool.getBankCard().getTokenProviderDeprecated().name()) + : null) .paymentSystem(PaymentSystemUtil.getPaymentSystemName(paymentTool.getBankCard())) .issuerCountry(paymentTool.getBankCard().getIssuerCountry() != null - ? paymentTool.getBankCard().getIssuerCountry().name() : null) + ? paymentTool.getBankCard().getIssuerCountry().name() + : null) .bankName(paymentTool.getBankCard().getBankName()) .detailsType(PaymentToolDetails.DetailsTypeEnum.PAYMENTTOOLDETAILSBANKCARD); } else if (paymentTool.isSetPaymentTerminal()) { @@ -41,7 +39,6 @@ public class PaymentToolUtils { TerminalPaymentUtil.getTerminalPaymentProviderName(paymentTool.getPaymentTerminal()))) .detailsType(PaymentToolDetails.DetailsTypeEnum.PAYMENTTOOLDETAILSPAYMENTTERMINAL); } else if (paymentTool.isSetDigitalWallet()) { - //TODO Bump swag-webhook-events api LegacyDigitalWalletProvider walletProvider = LegacyDigitalWalletProvider.valueOf( DigitalWalletUtil.getDigitalWalletName(paymentTool.getDigitalWallet())); if (walletProvider == LegacyDigitalWalletProvider.qiwi) { diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yml similarity index 83% rename from src/main/resources/application.yaml rename to src/main/resources/application.yml index 2a2b500..4fb5efa 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yml @@ -63,7 +63,11 @@ kafka: id: mg-events-customer enabled: false concurrency: 1 - + topic: + webhook-dispatcher: + name: webhook-dispatcher-topic + produce: + enabled: true info: version: '@version@' responsible: Inal Arsanukaev @@ -77,18 +81,6 @@ service: customer: url: http://hellgate:8022/v1/processing/customer_management networkTimeout: 5000 - fault-detector: - url: http://fault-detector:8022/v1/ - networkTimeout: 5000 - slidingWindow: 60000 - operationTimeLimit: 3000 - -cache: - invoice: - size: 10000 - -# connection timeout -merchant.callback.timeout: 10 limit: perShop: 10 @@ -106,19 +98,6 @@ spring.datasource: data-source-properties: reWriteBatchedInserts: true -db: - jdbc: - tr_timeout: 300000 - -message: - scheduler: - delay: 1000 - invoicing: - threadPoolSize: 10 - customer: - threadPoolSize: 3 - - clean: scheduler: cron: "0 0 * * * *" diff --git a/src/main/resources/db/migration/V27__drop_customer_event_id_not_null.sql b/src/main/resources/db/migration/V27__drop_customer_event_id_not_null.sql new file mode 100644 index 0000000..b10a003 --- /dev/null +++ b/src/main/resources/db/migration/V27__drop_customer_event_id_not_null.sql @@ -0,0 +1 @@ +ALTER TABLE hook.customer_message ALTER COLUMN event_id DROP NOT NULL; \ No newline at end of file diff --git a/src/test/java/dev/vality/hooker/AbstractIntegrationTest.java b/src/test/java/dev/vality/hooker/AbstractIntegrationTest.java index 2303662..d328990 100644 --- a/src/test/java/dev/vality/hooker/AbstractIntegrationTest.java +++ b/src/test/java/dev/vality/hooker/AbstractIntegrationTest.java @@ -25,7 +25,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen public abstract class AbstractIntegrationTest { @ClassRule - public static PostgreSQLContainer postgres = (PostgreSQLContainer) new PostgreSQLContainer("postgres:14") + public static PostgreSQLContainer postgres = (PostgreSQLContainer) new PostgreSQLContainer("postgres:12") .withStartupTimeout(Duration.ofMinutes(5)); @Value("${local.server.port}") protected int port; @@ -35,13 +35,13 @@ public abstract class AbstractIntegrationTest { public void initialize(ConfigurableApplicationContext configurableApplicationContext) { log.info("Postgres URL: " + postgres.getJdbcUrl()); TestPropertyValues.of( - "spring.datasource.url=" + postgres.getJdbcUrl(), - "spring.datasource.username=" + postgres.getUsername(), - "spring.datasource.password=" + postgres.getPassword(), - "flyway.url=" + postgres.getJdbcUrl(), - "flyway.user=" + postgres.getUsername(), - "flyway.password=" + postgres.getPassword() - ) + "spring.datasource.url=" + postgres.getJdbcUrl(), + "spring.datasource.username=" + postgres.getUsername(), + "spring.datasource.password=" + postgres.getPassword(), + "flyway.url=" + postgres.getJdbcUrl(), + "flyway.user=" + postgres.getUsername(), + "flyway.password=" + postgres.getPassword() + ) .applyTo(configurableApplicationContext); } } diff --git a/src/test/java/dev/vality/hooker/config/PostgresqlSpringBootITest.java b/src/test/java/dev/vality/hooker/config/PostgresqlSpringBootITest.java new file mode 100644 index 0000000..30c2b8a --- /dev/null +++ b/src/test/java/dev/vality/hooker/config/PostgresqlSpringBootITest.java @@ -0,0 +1,17 @@ +package dev.vality.hooker.config; + + +import dev.vality.testcontainers.annotations.DefaultSpringBootTest; +import dev.vality.testcontainers.annotations.postgresql.PostgresqlTestcontainerSingleton; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@PostgresqlTestcontainerSingleton +@DefaultSpringBootTest +public @interface PostgresqlSpringBootITest { +} \ No newline at end of file diff --git a/src/test/java/dev/vality/hooker/converter/CustomerBindingConverterTest.java b/src/test/java/dev/vality/hooker/converter/CustomerBindingConverterTest.java index 29b7c53..6242860 100644 --- a/src/test/java/dev/vality/hooker/converter/CustomerBindingConverterTest.java +++ b/src/test/java/dev/vality/hooker/converter/CustomerBindingConverterTest.java @@ -1,20 +1,25 @@ package dev.vality.hooker.converter; -import dev.vality.damsel.domain.*; +import dev.vality.damsel.domain.BankCard; +import dev.vality.damsel.domain.PaymentTool; import dev.vality.damsel.payment_processing.CustomerBinding; import dev.vality.geck.serializer.kit.mock.MockMode; import dev.vality.geck.serializer.kit.mock.MockTBaseProcessor; import dev.vality.geck.serializer.kit.tbase.TBaseHandler; -import dev.vality.hooker.AbstractIntegrationTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; import java.io.IOException; -import static io.github.benas.randombeans.api.EnhancedRandom.random; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class CustomerBindingConverterTest extends AbstractIntegrationTest { +@ContextConfiguration(classes = { + CustomerBindingConverter.class +}) +@SpringBootTest +public class CustomerBindingConverterTest { @Autowired private CustomerBindingConverter converter; @@ -25,15 +30,7 @@ public class CustomerBindingConverterTest extends AbstractIntegrationTest { CustomerBinding source = mockTBaseProcessor .process(new CustomerBinding(), new TBaseHandler<>(CustomerBinding.class)); source.getPaymentResource().setPaymentTool( - PaymentTool.bank_card(mockTBaseProcessor.process( - new BankCard() - .setPaymentSystem( - new PaymentSystemRef(random(LegacyBankCardPaymentSystem.class).name()) - ) - .setPaymentToken( - new BankCardTokenServiceRef(random(LegacyBankCardTokenProvider.class).name()) - ), - new TBaseHandler<>(BankCard.class)))); + PaymentTool.bank_card(mockTBaseProcessor.process(new BankCard(), new TBaseHandler<>(BankCard.class)))); dev.vality.swag_webhook_events.model.CustomerBinding target = converter.convert(source); assertEquals(source.getId(), target.getId()); assertEquals(source.getPaymentResource().getPaymentSessionId(), diff --git a/src/test/java/dev/vality/hooker/converter/CustomerConverterTest.java b/src/test/java/dev/vality/hooker/converter/CustomerConverterTest.java index c009ce4..9e29910 100644 --- a/src/test/java/dev/vality/hooker/converter/CustomerConverterTest.java +++ b/src/test/java/dev/vality/hooker/converter/CustomerConverterTest.java @@ -1,20 +1,28 @@ package dev.vality.hooker.converter; +import com.fasterxml.jackson.databind.ObjectMapper; import dev.vality.damsel.json.Value; import dev.vality.damsel.payment_processing.Customer; import dev.vality.geck.serializer.kit.mock.MockMode; import dev.vality.geck.serializer.kit.mock.MockTBaseProcessor; import dev.vality.geck.serializer.kit.tbase.TBaseHandler; -import dev.vality.hooker.AbstractIntegrationTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; import java.io.IOException; import java.util.HashMap; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class CustomerConverterTest extends AbstractIntegrationTest { +@ContextConfiguration(classes = { + CustomerConverter.class, + MetadataDeserializer.class, + ObjectMapper.class +}) +@SpringBootTest +public class CustomerConverterTest { @Autowired private CustomerConverter converter; @@ -29,4 +37,4 @@ public class CustomerConverterTest extends AbstractIntegrationTest { assertEquals(source.getShopId(), target.getShopID()); assertEquals(source.getStatus().getSetField().getFieldName(), target.getStatus().getValue()); } -} +} \ No newline at end of file diff --git a/src/test/java/dev/vality/hooker/converter/CustomerMessageDaoImplTest.java b/src/test/java/dev/vality/hooker/converter/CustomerMessageDaoImplTest.java new file mode 100644 index 0000000..4fc037f --- /dev/null +++ b/src/test/java/dev/vality/hooker/converter/CustomerMessageDaoImplTest.java @@ -0,0 +1,57 @@ +package dev.vality.hooker.converter; + +import dev.vality.hooker.config.PostgresqlSpringBootITest; +import dev.vality.hooker.dao.impl.CustomerDaoImpl; +import dev.vality.hooker.model.CustomerMessage; +import dev.vality.hooker.model.CustomerMessageEnum; +import dev.vality.hooker.model.EventType; +import dev.vality.hooker.utils.BuildUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; + +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@PostgresqlSpringBootITest +public class CustomerMessageDaoImplTest { + + @Autowired + private CustomerDaoImpl messageDao; + + @Autowired + private NamedParameterJdbcTemplate jdbcTemplate; + + @BeforeEach + public void setUp() throws Exception { + CustomerMessage message = + BuildUtils.buildCustomerMessage(1L, "1234", EventType.CUSTOMER_CREATED, + CustomerMessageEnum.CUSTOMER, "124", + "4356"); + message.setSequenceId(1L); + message.setChangeId(1); + messageDao.save(message); + } + + @Test + public void testDuplication() { + CustomerMessage message = + BuildUtils.buildCustomerMessage(1L, "1234", EventType.CUSTOMER_CREATED, + CustomerMessageEnum.CUSTOMER, "124", + "4356"); + message.setSequenceId(1L); + message.setChangeId(1); + messageDao.save(message); + assertEquals(1, + jdbcTemplate.queryForList("select 1 from hook.customer_message", Map.of(), Integer.class).size()); + } + + @Test + public void get() throws Exception { + CustomerMessage message = messageDao.getAny("124", CustomerMessageEnum.CUSTOMER); + assertEquals(message.getShopId(), "4356"); + } + +} diff --git a/src/test/java/dev/vality/hooker/converter/InvoiceConverterTest.java b/src/test/java/dev/vality/hooker/converter/InvoiceConverterTest.java index 412dc4b..3391e06 100644 --- a/src/test/java/dev/vality/hooker/converter/InvoiceConverterTest.java +++ b/src/test/java/dev/vality/hooker/converter/InvoiceConverterTest.java @@ -1,18 +1,26 @@ package dev.vality.hooker.converter; +import com.fasterxml.jackson.databind.ObjectMapper; import dev.vality.damsel.domain.Invoice; import dev.vality.geck.serializer.kit.mock.MockMode; import dev.vality.geck.serializer.kit.mock.MockTBaseProcessor; import dev.vality.geck.serializer.kit.tbase.TBaseHandler; -import dev.vality.hooker.AbstractIntegrationTest; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; import java.io.IOException; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class InvoiceConverterTest extends AbstractIntegrationTest { +@ContextConfiguration(classes = { + InvoiceConverter.class, + MetadataDeserializer.class, + ObjectMapper.class +}) +@SpringBootTest +public class InvoiceConverterTest { @Autowired private InvoiceConverter converter; diff --git a/src/test/java/dev/vality/hooker/converter/MetadataDeserializerTest.java b/src/test/java/dev/vality/hooker/converter/MetadataDeserializerTest.java index c61e261..816053c 100644 --- a/src/test/java/dev/vality/hooker/converter/MetadataDeserializerTest.java +++ b/src/test/java/dev/vality/hooker/converter/MetadataDeserializerTest.java @@ -3,17 +3,26 @@ package dev.vality.hooker.converter; import com.fasterxml.jackson.databind.ObjectMapper; import dev.vality.damsel.json.Null; import dev.vality.damsel.json.Value; -import org.junit.Test; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; import java.util.List; import java.util.Map; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +@ContextConfiguration(classes = { + MetadataDeserializer.class, + ObjectMapper.class +}) +@SpringBootTest public class MetadataDeserializerTest { - private final MetadataDeserializer metadataDeserializer = new MetadataDeserializer(new ObjectMapper()); + @Autowired + private MetadataDeserializer metadataDeserializer; @Test public void deserialize() { diff --git a/src/test/java/dev/vality/hooker/converter/PaymentConverterTest.java b/src/test/java/dev/vality/hooker/converter/PaymentConverterTest.java index 0056d8d..a9fcf15 100644 --- a/src/test/java/dev/vality/hooker/converter/PaymentConverterTest.java +++ b/src/test/java/dev/vality/hooker/converter/PaymentConverterTest.java @@ -1,25 +1,32 @@ package dev.vality.hooker.converter; +import com.fasterxml.jackson.databind.ObjectMapper; import dev.vality.damsel.domain.*; import dev.vality.geck.serializer.kit.mock.MockMode; import dev.vality.geck.serializer.kit.mock.MockTBaseProcessor; import dev.vality.geck.serializer.kit.tbase.TBaseHandler; -import dev.vality.hooker.AbstractIntegrationTest; import dev.vality.swag_webhook_events.model.CustomerPayer; import dev.vality.swag_webhook_events.model.Payment; import dev.vality.swag_webhook_events.model.PaymentResourcePayer; import dev.vality.swag_webhook_events.model.RecurrentPayer; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; import java.io.IOException; +import java.util.List; -import static io.github.benas.randombeans.api.EnhancedRandom.random; -import static java.util.List.of; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; -public class PaymentConverterTest extends AbstractIntegrationTest { +@ContextConfiguration(classes = { + PaymentConverter.class, + MetadataDeserializer.class, + ObjectMapper.class +}) +@SpringBootTest +public class PaymentConverterTest { @Autowired private PaymentConverter converter; @@ -30,32 +37,17 @@ public class PaymentConverterTest extends AbstractIntegrationTest { InvoicePayment source = mockTBaseProcessor .process(new InvoicePayment(), new TBaseHandler<>(InvoicePayment.class)); source.setCreatedAt("2016-03-22T06:12:27Z"); - BankCard bankCard = new BankCard() - .setPaymentSystem( - new PaymentSystemRef( - random(LegacyBankCardPaymentSystem.class).name() - ) - ) - .setPaymentToken( - new BankCardTokenServiceRef(random(LegacyBankCardTokenProvider.class).name()) - ); if (source.getPayer().isSetPaymentResource()) { - source.getPayer().getPaymentResource() - .getResource() - .setPaymentTool( - PaymentTool.bank_card( - mockTBaseProcessor.process( - bankCard, - new TBaseHandler<>(BankCard.class) - ) - )); + source.getPayer().getPaymentResource().getResource() + .setPaymentTool(PaymentTool + .bank_card(mockTBaseProcessor.process(new BankCard(), new TBaseHandler<>(BankCard.class)))); } + source.setStatus(InvoicePaymentStatus.pending(new InvoicePaymentPending())); Payment target = converter - .convert(new dev.vality.damsel.payment_processing.InvoicePayment(source, of(), of(), of(), of())); + .convert(new dev.vality.damsel.payment_processing.InvoicePayment(source, + List.of(), List.of(), List.of(), List.of())); assertEquals(source.getId(), target.getId()); - if (!source.getStatus().isSetChargedBack()) { - assertEquals(source.getStatus().getSetField().getFieldName(), target.getStatus().getValue()); - } + assertEquals(source.getStatus().getSetField().getFieldName(), target.getStatus().getValue()); if (source.getStatus().isSetCaptured() && source.getStatus().getCaptured().isSetCost()) { assertEquals(source.getStatus().getCaptured().getCost().getAmount(), target.getAmount().longValue()); assertEquals(source.getStatus().getCaptured().getCost().getCurrency().getSymbolicCode(), diff --git a/src/test/java/dev/vality/hooker/converter/RefundConverterTest.java b/src/test/java/dev/vality/hooker/converter/RefundConverterTest.java index 196745a..67dcbe9 100644 --- a/src/test/java/dev/vality/hooker/converter/RefundConverterTest.java +++ b/src/test/java/dev/vality/hooker/converter/RefundConverterTest.java @@ -4,17 +4,22 @@ import dev.vality.damsel.domain.InvoicePaymentRefund; import dev.vality.geck.serializer.kit.mock.MockMode; import dev.vality.geck.serializer.kit.mock.MockTBaseProcessor; import dev.vality.geck.serializer.kit.tbase.TBaseHandler; -import dev.vality.hooker.AbstractIntegrationTest; import dev.vality.swag_webhook_events.model.Refund; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; import java.io.IOException; import static java.util.List.of; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class RefundConverterTest extends AbstractIntegrationTest { +@ContextConfiguration(classes = { + RefundConverter.class +}) +@SpringBootTest +public class RefundConverterTest { @Autowired private RefundConverter converter; @@ -30,4 +35,4 @@ public class RefundConverterTest extends AbstractIntegrationTest { assertEquals(source.getStatus().getSetField().getFieldName(), target.getStatus().getValue()); assertEquals(source.getReason(), target.getReason()); } -} +} \ No newline at end of file diff --git a/src/test/java/dev/vality/hooker/converter/WebhookMessageBuilderTest.java b/src/test/java/dev/vality/hooker/converter/WebhookMessageBuilderTest.java new file mode 100644 index 0000000..abd5da3 --- /dev/null +++ b/src/test/java/dev/vality/hooker/converter/WebhookMessageBuilderTest.java @@ -0,0 +1,61 @@ +package dev.vality.hooker.converter; + +import dev.vality.hooker.configuration.AppConfig; +import dev.vality.hooker.model.WebhookMessageModel; +import dev.vality.hooker.service.AdditionalHeadersGenerator; +import dev.vality.hooker.service.crypt.AsymSigner; +import dev.vality.swag_webhook_events.model.Event; +import dev.vality.webhook.dispatcher.WebhookMessage; +import org.apache.http.entity.ContentType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ContextConfiguration; + +import static io.github.benas.randombeans.api.EnhancedRandom.random; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.any; + +@ContextConfiguration(classes = { + WebhookMessageBuilder.class, + AdditionalHeadersGenerator.class, + AppConfig.class +}) +@SpringBootTest +public class WebhookMessageBuilderTest { + + @MockBean + private AsymSigner signer; + + @Autowired + private WebhookMessageBuilder builder; + + @BeforeEach + public void setUp() { + Mockito.when(signer.sign(any(), any())).thenReturn("signature"); + } + + @Test + public void testBuild() { + var webhookMessageModel = new WebhookMessageModel<>(); + webhookMessageModel.setHookId(1245L); + webhookMessageModel.setUrl("kek.url"); + webhookMessageModel.setPrivateKey(""); + Event event = random(Event.class); + String sourceId = "keks"; + long parentId = 1L; + WebhookMessage webhookMessage = builder.build(webhookMessageModel, event, sourceId, parentId); + assertEquals(sourceId, webhookMessage.getSourceId()); + assertEquals(parentId, webhookMessage.getParentEventId()); + assertEquals(webhookMessageModel.getHookId(), webhookMessage.getWebhookId()); + assertEquals(event.getEventID().longValue(), webhookMessage.getEventId()); + assertNotNull(webhookMessage.getAdditionalHeaders().get("Content-Signature")); + assertEquals(ContentType.APPLICATION_JSON.getMimeType(), webhookMessage.getContentType()); + assertNotNull(webhookMessage.getCreatedAt()); + assertNotNull(webhookMessage.getRequestBody()); + } +} \ No newline at end of file diff --git a/src/test/java/dev/vality/hooker/dao/impl/CleanTablesDaoTest.java b/src/test/java/dev/vality/hooker/dao/CleanTablesDaoTest.java similarity index 84% rename from src/test/java/dev/vality/hooker/dao/impl/CleanTablesDaoTest.java rename to src/test/java/dev/vality/hooker/dao/CleanTablesDaoTest.java index 5412fd4..00d366d 100644 --- a/src/test/java/dev/vality/hooker/dao/impl/CleanTablesDaoTest.java +++ b/src/test/java/dev/vality/hooker/dao/CleanTablesDaoTest.java @@ -1,16 +1,18 @@ -package dev.vality.hooker.dao.impl; +package dev.vality.hooker.dao; -import dev.vality.hooker.AbstractIntegrationTest; -import org.junit.Test; +import dev.vality.hooker.config.PostgresqlSpringBootITest; +import dev.vality.hooker.dao.impl.CleanTablesDao; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import java.util.stream.IntStream; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; -public class CleanTablesDaoTest extends AbstractIntegrationTest { +@PostgresqlSpringBootITest +public class CleanTablesDaoTest { @Autowired private CleanTablesDao cleanTablesDao; diff --git a/src/test/java/dev/vality/hooker/dao/CustomerDaoImplTest.java b/src/test/java/dev/vality/hooker/dao/CustomerDaoImplTest.java new file mode 100644 index 0000000..e37db93 --- /dev/null +++ b/src/test/java/dev/vality/hooker/dao/CustomerDaoImplTest.java @@ -0,0 +1,119 @@ +package dev.vality.hooker.dao; + +import dev.vality.hooker.config.PostgresqlSpringBootITest; +import dev.vality.hooker.dao.impl.CustomerDaoImpl; +import dev.vality.hooker.model.CustomerMessage; +import dev.vality.hooker.model.CustomerMessageEnum; +import dev.vality.hooker.model.EventType; +import dev.vality.hooker.model.Hook; +import dev.vality.hooker.utils.BuildUtils; +import dev.vality.swag_webhook_events.model.Event; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@PostgresqlSpringBootITest +public class CustomerDaoImplTest { + + @Autowired + private CustomerDaoImpl messageDao; + + @Autowired + private HookDao hookDao; + + private final String partyId = "56678"; + private final String customerIdOne = "1234"; + private final String customerIdTwo = "1235"; + private final String customerIdThree = "1236"; + + private Long messageIdOne; + private Long messageId1Two; + private Long messageId2Two; + private Long messageIdThree; + + private Hook hook; + + @BeforeEach + public void setUp() { + hook = Hook.builder() + .partyId(partyId) + .topic(Event.TopicEnum.CUSTOMERSTOPIC.getValue()) + .url("zzz") + .filters(Set.of( + WebhookAdditionalFilter.builder() + .eventType(EventType.CUSTOMER_CREATED) + .build(), + WebhookAdditionalFilter.builder() + .eventType(EventType.CUSTOMER_BINDING_STARTED) + .build())) + .build(); + + hookDao.create(hook); + messageIdOne = messageDao.save(BuildUtils.buildCustomerMessage(1L, partyId, EventType.CUSTOMER_CREATED, + CustomerMessageEnum.CUSTOMER, customerIdOne, "shop")); + messageId1Two = messageDao.save(BuildUtils.buildCustomerMessage(1L, partyId, EventType.CUSTOMER_CREATED, + CustomerMessageEnum.CUSTOMER, customerIdTwo, "shop")); + messageId2Two = messageDao.save(BuildUtils.buildCustomerMessage(1L, partyId, EventType.CUSTOMER_BINDING_STARTED, + CustomerMessageEnum.BINDING, customerIdTwo, "shop")); + messageIdThree = messageDao.save(BuildUtils.buildCustomerMessage(1L, partyId, EventType.CUSTOMER_DELETED, + CustomerMessageEnum.CUSTOMER, customerIdThree, "shop")); + + } + + @Test + public void testGetInvoicingMessage() { + CustomerMessage messageOne = messageDao.getAny(customerIdOne, CustomerMessageEnum.CUSTOMER); + assertEquals(customerIdOne, messageOne.getSourceId()); + assertEquals(EventType.CUSTOMER_CREATED, messageOne.getEventType()); + assertEquals(partyId, messageOne.getPartyId()); + + CustomerMessage messageTwo = messageDao.getAny(customerIdTwo, CustomerMessageEnum.BINDING); + assertEquals(customerIdTwo, messageTwo.getSourceId()); + assertEquals(EventType.CUSTOMER_BINDING_STARTED, messageTwo.getEventType()); + assertEquals(partyId, messageTwo.getPartyId()); + } + + @Test + public void testGetWebhookModels() { + var webhookModelsOne = messageDao.getWebhookModels(messageIdOne); + assertEquals(1, webhookModelsOne.size()); + assertEquals(hook.getId(), webhookModelsOne.get(0).getHookId()); + assertEquals(customerIdOne, webhookModelsOne.get(0).getMessage().getSourceId()); + assertEquals(EventType.CUSTOMER_CREATED, webhookModelsOne.get(0).getMessage().getEventType()); + + var webhookModels1Two = messageDao.getWebhookModels(messageId1Two); + assertEquals(hook.getId(), webhookModels1Two.get(0).getHookId()); + assertEquals(customerIdTwo, webhookModels1Two.get(0).getMessage().getSourceId()); + assertEquals(EventType.CUSTOMER_CREATED, webhookModels1Two.get(0).getMessage().getEventType()); + + var webhookModels2Two = messageDao.getWebhookModels(messageId2Two); + assertEquals(hook.getId(), webhookModels2Two.get(0).getHookId()); + assertEquals(customerIdTwo, webhookModels2Two.get(0).getMessage().getSourceId()); + assertEquals(CustomerMessageEnum.BINDING, webhookModels2Two.get(0).getMessage().getType()); + assertEquals(EventType.CUSTOMER_BINDING_STARTED, webhookModels2Two.get(0).getMessage().getEventType()); + + var webhookModelsThree = messageDao.getWebhookModels(messageIdThree); + assertEquals(0, webhookModelsThree.size()); + } + + @Test + public void testGetParentEventId() { + Long parentEventIdOne = messageDao.getParentId(hook.getId(), customerIdOne, messageIdOne); + assertEquals(-1, parentEventIdOne); + + Long parentEventId1Two = messageDao.getParentId(hook.getId(), customerIdTwo, messageId1Two); + assertEquals(-1, parentEventId1Two); + + Long parentEventId2Two = messageDao.getParentId(hook.getId(), customerIdTwo, messageId2Two); + var webhookModels1Two = messageDao.getWebhookModels(messageId1Two); + assertEquals(1, webhookModels1Two.size()); + assertEquals(parentEventId2Two, messageId1Two); + + Long parentEventIdThree = messageDao.getParentId(hook.getId(), customerIdThree, messageIdThree); + assertEquals(-1, parentEventIdThree); + } +} diff --git a/src/test/java/dev/vality/hooker/dao/CustomerMessageDaoImplTest.java b/src/test/java/dev/vality/hooker/dao/CustomerMessageDaoImplTest.java deleted file mode 100644 index 25d2b03..0000000 --- a/src/test/java/dev/vality/hooker/dao/CustomerMessageDaoImplTest.java +++ /dev/null @@ -1,67 +0,0 @@ -package dev.vality.hooker.dao; - -import dev.vality.hooker.AbstractIntegrationTest; -import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.model.CustomerMessage; -import dev.vality.hooker.model.CustomerMessageEnum; -import dev.vality.hooker.model.EventType; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.Arrays; - -import static dev.vality.hooker.utils.BuildUtils.buildCustomerMessage; -import static org.junit.Assert.assertEquals; - -/** - * Created by inalarsanukaev on 09.04.17. - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class CustomerMessageDaoImplTest extends AbstractIntegrationTest { - private static Logger log = LoggerFactory.getLogger(CustomerMessageDaoImplTest.class); - private static boolean messagesCreated = false; - @Autowired - CustomerDaoImpl messageDao; - - @Before - public void setUp() throws Exception { - if (!messagesCreated) { - CustomerMessage message = - buildCustomerMessage(1L, "1234", EventType.CUSTOMER_CREATED, CustomerMessageEnum.CUSTOMER, "124", - "4356"); - message.setSequenceId(1L); - message.setChangeId(1); - messageDao.create(message); - messagesCreated = true; - } - } - - @Test - public void testDuplication() { - CustomerMessage message = - buildCustomerMessage(1L, "1234", EventType.CUSTOMER_CREATED, CustomerMessageEnum.CUSTOMER, "124", - "4356"); - message.setSequenceId(1L); - message.setChangeId(1); - messageDao.create(message); - assertEquals(1, messageDao.getBy(Arrays.asList(1L, 2L, 3L, 4L, 5L, 6L, 7L)).size()); - } - - @Test - public void get() throws Exception { - CustomerMessage message = messageDao.getAny("124", CustomerMessageEnum.CUSTOMER); - assertEquals(message.getShopId(), "4356"); - } - - @Test - public void getMaxEventId() { - assertEquals(messageDao.getMaxEventId().longValue(), 1L); - } -} diff --git a/src/test/java/dev/vality/hooker/dao/HookDaoImplTest.java b/src/test/java/dev/vality/hooker/dao/HookDaoImplTest.java index 05e5262..7b06a1f 100644 --- a/src/test/java/dev/vality/hooker/dao/HookDaoImplTest.java +++ b/src/test/java/dev/vality/hooker/dao/HookDaoImplTest.java @@ -2,23 +2,19 @@ package dev.vality.hooker.dao; import dev.vality.damsel.webhooker.EventFilter; import dev.vality.damsel.webhooker.WebhookParams; -import dev.vality.hooker.AbstractIntegrationTest; +import dev.vality.hooker.config.PostgresqlSpringBootITest; import dev.vality.hooker.model.EventType; import dev.vality.hooker.model.Hook; import dev.vality.hooker.model.PartyMetadata; import dev.vality.hooker.utils.EventFilterUtils; import dev.vality.hooker.utils.HookConverter; import dev.vality.swag_webhook_events.model.Event; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList; import java.util.HashSet; @@ -26,18 +22,15 @@ import java.util.List; import java.util.Set; import java.util.stream.Collectors; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.*; /** * Created by inalarsanukaev on 08.04.17. */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class HookDaoImplTest extends AbstractIntegrationTest { +@PostgresqlSpringBootITest +public class HookDaoImplTest { - List ids = new ArrayList<>(); + private List ids = new ArrayList<>(); @Autowired private NamedParameterJdbcTemplate jdbcTemplate; @Autowired @@ -72,7 +65,7 @@ public class HookDaoImplTest extends AbstractIntegrationTest { return hook; } - @Before + @BeforeEach public void setUp() throws Exception { Set webhookAdditionalFilters = new HashSet<>(); webhookAdditionalFilters @@ -103,7 +96,7 @@ public class HookDaoImplTest extends AbstractIntegrationTest { ids.add(hook.getId()); String pubKey1 = hook.getPubKey(); String pubKey2 = hook.getPubKey(); - Assert.assertEquals(pubKey1, pubKey2); + assertEquals(pubKey1, pubKey2); webhookAdditionalFilters.clear(); webhookAdditionalFilters.add(WebhookAdditionalFilter.builder().eventType(EventType.CUSTOMER_CREATED).build()); webhookAdditionalFilters @@ -113,7 +106,7 @@ public class HookDaoImplTest extends AbstractIntegrationTest { hook = hookDao.create(HookConverter.convert(webhookParams)); } - @After + @AfterEach public void tearDown() throws Exception { List list = hookDao.getPartyHooks("123"); for (Hook w : list) { @@ -142,10 +135,14 @@ public class HookDaoImplTest extends AbstractIntegrationTest { @Test public void getPartyWebhooks() throws Exception { - assertEquals(hookDao.getPartyHooks("123").stream().filter(Hook::isEnabled).collect(Collectors.toList()).size(), - 3); - Assert.assertTrue( - hookDao.getPartyHooks("88888").stream().filter(Hook::isEnabled).collect(Collectors.toList()).isEmpty()); + List partyHooks = hookDao.getPartyHooks("123").stream() + .filter(Hook::isEnabled) + .collect(Collectors.toList()); + assertEquals(3, partyHooks.size()); + List notExistsPartyHooks = hookDao.getPartyHooks("88888").stream() + .filter(Hook::isEnabled) + .collect(Collectors.toList()); + assertTrue(notExistsPartyHooks.isEmpty()); } @Test diff --git a/src/test/java/dev/vality/hooker/dao/HookDeleteDaoTest.java b/src/test/java/dev/vality/hooker/dao/HookDeleteDaoTest.java deleted file mode 100644 index 40eded7..0000000 --- a/src/test/java/dev/vality/hooker/dao/HookDeleteDaoTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package dev.vality.hooker.dao; - -import dev.vality.hooker.AbstractIntegrationTest; -import dev.vality.hooker.dao.impl.CustomerDaoImpl; -import dev.vality.hooker.dao.impl.CustomerQueueDao; -import dev.vality.hooker.dao.impl.CustomerTaskDao; -import dev.vality.hooker.dao.impl.InvoicingQueueDao; -import dev.vality.hooker.dao.impl.InvoicingTaskDao; -import dev.vality.hooker.model.CustomerMessageEnum; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.Hook; -import dev.vality.hooker.model.InvoiceStatusEnum; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.PaymentStatusEnum; -import dev.vality.hooker.service.BatchService; -import dev.vality.hooker.utils.BuildUtils; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.TestPropertySource; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.Collections; - -import static dev.vality.hooker.utils.BuildUtils.buildCustomerMessage; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertTrue; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@TestPropertySource(properties = "message.scheduler.invoicing.threadPoolSize=0") -public class HookDeleteDaoTest extends AbstractIntegrationTest { - - @Autowired - InvoicingTaskDao taskDao; - - @Autowired - CustomerTaskDao customerTaskDao; - - @Autowired - InvoicingQueueDao queueDao; - - @Autowired - CustomerQueueDao customerQueueDao; - - @Autowired - HookDao hookDao; - - @Autowired - CustomerDaoImpl customerDaoImpl; - - @Autowired - BatchService batchService; - - @Test - public void testDelete() { - Hook hook1 = hookDao.create(HookDaoImplTest.buildHook("partyId", "fake.url")); - Hook hook2 = hookDao.create(HookDaoImplTest.buildHook("partyId2", "fake2.url")); - batchService.process(Collections.singletonList(BuildUtils - .buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "2345", hook1.getPartyId(), - EventType.INVOICE_CREATED, InvoiceStatusEnum.FULFILLED, PaymentStatusEnum.CAPTURED))); - assertEquals(queueDao.getWithPolicies(taskDao.getScheduled().keySet()).size(), 1); - - hookDao.delete(hook2.getId()); - assertNotEquals(queueDao.getWithPolicies(taskDao.getScheduled().keySet()).size(), 0); - hookDao.delete(hook1.getId()); - assertTrue(taskDao.getScheduled().keySet().isEmpty()); - assertFalse(hookDao.getHookById(hook1.getId()).isEnabled()); - assertFalse(hookDao.getHookById(hook2.getId()).isEnabled()); - } - - @Test - public void testDeleteCustomerHooks() { - Hook hook = hookDao.create(HookDaoImplTest.buildCustomerHook("partyId", "fake.url")); - Long messageId = customerDaoImpl.create(buildCustomerMessage(1L, hook.getPartyId(), EventType.CUSTOMER_CREATED, - CustomerMessageEnum.CUSTOMER, "124", "4356")); - customerQueueDao.createWithPolicy(messageId); - customerTaskDao.create(messageId); - assertEquals(customerQueueDao.getWithPolicies(customerTaskDao.getScheduled().keySet()).size(), 1); - hookDao.delete(hook.getId()); - assertTrue(customerTaskDao.getScheduled().keySet().isEmpty()); - assertFalse(hookDao.getHookById(hook.getId()).isEnabled()); - } -} diff --git a/src/test/java/dev/vality/hooker/dao/InvoicingDaoImplTest.java b/src/test/java/dev/vality/hooker/dao/InvoicingDaoImplTest.java new file mode 100644 index 0000000..208311f --- /dev/null +++ b/src/test/java/dev/vality/hooker/dao/InvoicingDaoImplTest.java @@ -0,0 +1,156 @@ +package dev.vality.hooker.dao; + +import dev.vality.hooker.config.PostgresqlSpringBootITest; +import dev.vality.hooker.dao.impl.InvoicingDaoImpl; +import dev.vality.hooker.model.*; +import dev.vality.hooker.utils.BuildUtils; +import dev.vality.swag_webhook_events.model.Event; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +@PostgresqlSpringBootITest +public class InvoicingDaoImplTest { + + @Autowired + private InvoicingDaoImpl messageDao; + + @Autowired + private HookDao hookDao; + + private final String partyId = "56678"; + private final String invoiceOne = "1234"; + private final String invoiceTwo = "1235"; + private final String invoiceThree = "1236"; + + private Long messageIdOne; + private Long messageIdCreatedTwo; + private Long messageIdProcessedTwo; + private Long messageIdCapturedTwo; + private Long messageIdThree; + + private Hook hook; + + @BeforeEach + public void setUp() { + hook = Hook.builder() + .partyId(partyId) + .topic(Event.TopicEnum.INVOICESTOPIC.getValue()) + .url("zzz") + .filters(Set.of( + WebhookAdditionalFilter.builder() + .eventType(EventType.INVOICE_CREATED) + .build(), + WebhookAdditionalFilter.builder() + .eventType(EventType.INVOICE_PAYMENT_STATUS_CHANGED) + .invoicePaymentStatus("processed") + .build(), + WebhookAdditionalFilter.builder() + .eventType(EventType.INVOICE_PAYMENT_STATUS_CHANGED) + .invoicePaymentStatus("captured") + .build() + )) + .build(); + + hookDao.create(hook); + messageIdOne = messageDao.save(BuildUtils.buildMessage(InvoicingMessageEnum.INVOICE.getValue(), + invoiceOne, partyId, EventType.INVOICE_CREATED, + InvoiceStatusEnum.UNPAID, null)); + messageIdCreatedTwo = messageDao.save(BuildUtils.buildMessage(InvoicingMessageEnum.INVOICE.getValue(), + invoiceTwo, partyId, EventType.INVOICE_CREATED, + InvoiceStatusEnum.UNPAID, null, 1L, 1)); + messageIdProcessedTwo = messageDao.save(BuildUtils.buildMessage(InvoicingMessageEnum.PAYMENT.getValue(), + invoiceTwo, partyId, EventType.INVOICE_PAYMENT_STATUS_CHANGED, + InvoiceStatusEnum.PAID, PaymentStatusEnum.PROCESSED, 1L, 2)); + messageIdCapturedTwo = messageDao.save(BuildUtils.buildMessage(InvoicingMessageEnum.PAYMENT.getValue(), + invoiceTwo, partyId, EventType.INVOICE_PAYMENT_STATUS_CHANGED, + InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED, 1L, 3)); + messageIdThree = messageDao.save(BuildUtils.buildMessage(InvoicingMessageEnum.INVOICE.getValue(), + invoiceThree, partyId, EventType.INVOICE_STATUS_CHANGED, + InvoiceStatusEnum.PAID, null)); + } + + @Test + public void testGetInvoicingMessage() { + InvoicingMessage messageOne = messageDao.getInvoicingMessage( + InvoicingMessageKey.builder() + .invoiceId(invoiceOne) + .type(InvoicingMessageEnum.INVOICE) + .build()); + assertEquals(invoiceOne, messageOne.getSourceId()); + assertEquals(InvoiceStatusEnum.UNPAID, messageOne.getInvoiceStatus()); + assertEquals(partyId, messageOne.getPartyId()); + + InvoicingMessage messageTwo = messageDao.getInvoicingMessage( + InvoicingMessageKey.builder() + .invoiceId(invoiceTwo) + .paymentId("123") + .type(InvoicingMessageEnum.PAYMENT) + .build()); + assertEquals(invoiceTwo, messageTwo.getSourceId()); + assertEquals(InvoiceStatusEnum.PAID, messageTwo.getInvoiceStatus()); + assertEquals(PaymentStatusEnum.CAPTURED, messageTwo.getPaymentStatus()); + assertEquals(partyId, messageTwo.getPartyId()); + + assertNotEquals(messageIdCreatedTwo, messageIdProcessedTwo); + + InvoicingMessage messageThree = messageDao.getInvoicingMessage( + InvoicingMessageKey.builder() + .invoiceId(invoiceThree) + .type(InvoicingMessageEnum.INVOICE) + .build()); + assertEquals(invoiceThree, messageThree.getSourceId()); + assertEquals(InvoiceStatusEnum.PAID, messageThree.getInvoiceStatus()); + assertEquals(partyId, messageThree.getPartyId()); + } + + @Test + public void testGetWebhookModels() { + var webhookModelsOne = messageDao.getWebhookModels(messageIdOne); + assertEquals(1, webhookModelsOne.size()); + assertEquals(hook.getId(), webhookModelsOne.get(0).getHookId()); + assertEquals(invoiceOne, webhookModelsOne.get(0).getMessage().getSourceId()); + assertEquals(InvoiceStatusEnum.UNPAID, webhookModelsOne.get(0).getMessage().getInvoiceStatus()); + + var webhookModels1Two = messageDao.getWebhookModels(messageIdCreatedTwo); + assertEquals(hook.getId(), webhookModels1Two.get(0).getHookId()); + assertEquals(invoiceTwo, webhookModels1Two.get(0).getMessage().getSourceId()); + assertEquals(InvoiceStatusEnum.UNPAID, webhookModels1Two.get(0).getMessage().getInvoiceStatus()); + + var webhookModels2Two = messageDao.getWebhookModels(messageIdProcessedTwo); + assertEquals(hook.getId(), webhookModels2Two.get(0).getHookId()); + assertEquals(invoiceTwo, webhookModels2Two.get(0).getMessage().getSourceId()); + assertEquals(InvoiceStatusEnum.PAID, webhookModels2Two.get(0).getMessage().getInvoiceStatus()); + assertEquals(PaymentStatusEnum.PROCESSED, webhookModels2Two.get(0).getMessage().getPaymentStatus()); + + var webhookModelsThree = messageDao.getWebhookModels(messageIdThree); + assertEquals(0, webhookModelsThree.size()); + } + + @Test + public void testGetParentEventId() { + Long parentEventIdOne = messageDao.getParentId(hook.getId(), invoiceOne, messageIdOne); + assertEquals(-1, parentEventIdOne); + + Long parentEventIdCreatedTwo = messageDao.getParentId(hook.getId(), invoiceTwo, messageIdCreatedTwo); + assertEquals(-1, parentEventIdCreatedTwo); + + Long parentEventIdProcessedTwo = messageDao.getParentId(hook.getId(), invoiceTwo, messageIdProcessedTwo); + var webhookModels1Two = messageDao.getWebhookModels(messageIdCreatedTwo); + assertEquals(1, webhookModels1Two.size()); + assertEquals(parentEventIdProcessedTwo, messageIdCreatedTwo); + + Long parentEventIdCapturedTwo = messageDao.getParentId(hook.getId(), invoiceTwo, messageIdCapturedTwo); + var webhookModels2Two = messageDao.getWebhookModels(messageIdCreatedTwo); + assertEquals(1, webhookModels2Two.size()); + assertEquals(parentEventIdCapturedTwo, messageIdProcessedTwo); + + Long parentEventIdThree = messageDao.getParentId(hook.getId(), invoiceThree, messageIdThree); + assertEquals(-1, parentEventIdThree); + } +} diff --git a/src/test/java/dev/vality/hooker/dao/InvoicingMessageDaoImplTest.java b/src/test/java/dev/vality/hooker/dao/InvoicingMessageDaoImplTest.java deleted file mode 100644 index e8be3bc..0000000 --- a/src/test/java/dev/vality/hooker/dao/InvoicingMessageDaoImplTest.java +++ /dev/null @@ -1,76 +0,0 @@ -package dev.vality.hooker.dao; - -import dev.vality.hooker.AbstractIntegrationTest; -import dev.vality.hooker.dao.impl.InvoicingMessageDaoImpl; -import dev.vality.hooker.exception.NotFoundException; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoiceStatusEnum; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.model.PaymentStatusEnum; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.Arrays; -import java.util.List; - -import static dev.vality.hooker.utils.BuildUtils.buildMessage; -import static org.junit.Assert.assertEquals; - -/** - * Created by inalarsanukaev on 09.04.17. - */ -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class InvoicingMessageDaoImplTest extends AbstractIntegrationTest { - private static Logger log = LoggerFactory.getLogger(InvoicingMessageDaoImplTest.class); - private static boolean messagesCreated = false; - @Autowired - InvoicingMessageDaoImpl messageDao; - - @Before - public void setUp() throws Exception { - if (!messagesCreated) { - messageDao.saveBatch(Arrays.asList( - buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "1234", "56678", EventType.INVOICE_CREATED, - InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED), - buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "1235", "56678", EventType.INVOICE_CREATED, - InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED), - buildMessage(InvoicingMessageEnum.PAYMENT.getValue(), "1236", "56678", EventType.INVOICE_CREATED, - InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED))); - messagesCreated = true; - } - } - - @Test - public void get() throws Exception { - InvoicingMessage message = messageDao.getInvoicingMessage( - InvoicingMessageKey.builder().invoiceId("1235").type(InvoicingMessageEnum.INVOICE).build()); - assertEquals(message.getInvoiceId(), "1235"); - assertEquals(message.getInvoiceStatus(), InvoiceStatusEnum.PAID); - - List messages = messageDao.getBy(Arrays.asList(message.getId())); - assertEquals(1, messages.size()); - assertEquals(messages.get(0).getPartyId(), "56678"); - - InvoicingMessage payment = messageDao.getInvoicingMessage( - InvoicingMessageKey.builder().invoiceId("1236").paymentId("123").type(InvoicingMessageEnum.PAYMENT) - .build()); - assertEquals("123", payment.getPaymentId()); - } - - @Ignore - @Test(expected = NotFoundException.class) - public void testNotFound() { - messageDao.getInvoicingMessage( - InvoicingMessageKey.builder().invoiceId("kek").paymentId("lol").refundId("kk").build()); - } -} diff --git a/src/test/java/dev/vality/hooker/dao/InvoicingTaskDaoTest.java b/src/test/java/dev/vality/hooker/dao/InvoicingTaskDaoTest.java deleted file mode 100644 index fc29780..0000000 --- a/src/test/java/dev/vality/hooker/dao/InvoicingTaskDaoTest.java +++ /dev/null @@ -1,263 +0,0 @@ -package dev.vality.hooker.dao; - -import dev.vality.hooker.AbstractIntegrationTest; -import dev.vality.hooker.dao.impl.InvoicingMessageDaoImpl; -import dev.vality.hooker.dao.impl.InvoicingQueueDao; -import dev.vality.hooker.dao.impl.InvoicingTaskDao; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.Hook; -import dev.vality.hooker.model.InvoiceStatusEnum; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.model.Message; -import dev.vality.hooker.model.PaymentStatusEnum; -import dev.vality.hooker.model.Task; -import dev.vality.hooker.utils.BuildUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.test.context.TestPropertySource; -import org.springframework.transaction.support.TransactionTemplate; - -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * Created by jeckep on 17.04.17. - */ - -@TestPropertySource(properties = "message.scheduler.invoicing.threadPoolSize=0") -public class InvoicingTaskDaoTest extends AbstractIntegrationTest { - - @Autowired - InvoicingTaskDao taskDao; - - @Autowired - InvoicingQueueDao queueDao; - - @Autowired - NamedParameterJdbcTemplate jdbcTemplate; - - @Autowired - HookDao hookDao; - - @Autowired - InvoicingMessageDaoImpl messageDao; - Long messageId; - Long hookId; - @Autowired - private TransactionTemplate transactionTemplate; - - @Before - public void setUp() throws Exception { - hookId = hookDao.create(HookDaoImplTest.buildHook("partyId", "fake.url")).getId(); - } - - @After - public void after() throws Exception { - jdbcTemplate.update( - "truncate hook.scheduled_task, hook.invoicing_queue, " + - " hook.message, hook.webhook_to_events, hook.webhook", - new HashMap<>()); - } - - @Test - public void createDeleteGet() { - messageDao.saveBatch(Collections.singletonList(BuildUtils - .buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "2345", "partyId", EventType.INVOICE_CREATED, - InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED))); - messageId = messageDao.getInvoicingMessage( - InvoicingMessageKey.builder().invoiceId("2345").type(InvoicingMessageEnum.INVOICE).build()).getId(); - queueDao.saveBatchWithPolicies(Collections.singletonList(messageId)); - taskDao.save(Collections.singletonList(messageId)); - Map > scheduled = taskDao.getScheduled(); - assertEquals(1, scheduled.size()); - taskDao.remove(scheduled.keySet().iterator().next(), messageId); - assertEquals(0, taskDao.getScheduled().size()); - } - - @Test - public void testSaveWithHookIdAndInvoiceId() { - messageDao.saveBatch(Collections.singletonList(BuildUtils - .buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "2345", "partyId", EventType.INVOICE_CREATED, - InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED))); - messageId = messageDao.getInvoicingMessage( - InvoicingMessageKey.builder().invoiceId("2345").type(InvoicingMessageEnum.INVOICE).build()).getId(); - queueDao.saveBatchWithPolicies(Collections.singletonList(messageId)); - int count = taskDao.save(hookId, "2345"); - assertEquals(1, count); - } - - @Test - public void testSelectForUpdate() throws InterruptedException { - - int cnt = 20; - - List messagesOne = IntStream.range(0, cnt).mapToObj(i -> BuildUtils - .buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "invoice_id1", "partyId", - EventType.INVOICE_CREATED, InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED)) - .collect(Collectors.toList()); - - messageDao.saveBatch(messagesOne); - List messageIdsOne = messagesOne.stream().map(Message::getId).collect(Collectors.toList()); - queueDao.saveBatchWithPolicies(messageIdsOne); - taskDao.save(messageIdsOne); - - List messagesSecond = IntStream.range(0, cnt).mapToObj(i -> BuildUtils - .buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "invoice_id2", "partyId", - EventType.INVOICE_CREATED, InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED)) - .collect(Collectors.toList()); - - messageDao.saveBatch(messagesSecond); - List messageIdsSecond = messagesSecond.stream().map(Message::getId).collect(Collectors.toList()); - queueDao.saveBatchWithPolicies(messageIdsSecond); - taskDao.save(messageIdsSecond); - - Set scheduledOne = new HashSet<>(); - new Thread(() -> transactionTemplate.execute(tr -> { - scheduledOne.addAll(taskDao.getScheduled().values().stream().flatMap(List::stream).map(Task::getMessageId) - .collect(Collectors.toSet())); - System.out.println("scheduledOne: " + scheduledOne); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return 1; - })).start(); - - Thread.sleep(100); - - assertEquals(cnt, scheduledOne.size()); - - Set scheduledTwo = new HashSet<>(); - new Thread(() -> transactionTemplate.execute(tr -> { - scheduledTwo.addAll(taskDao.getScheduled().values().stream().flatMap(List::stream).map(Task::getMessageId) - .collect(Collectors.toSet())); - System.out.println("scheduledTwo :" + scheduledTwo); - return 1; - })).start(); - - Thread.sleep(1000); - - assertEquals(cnt, scheduledTwo.size()); - - scheduledOne.retainAll(scheduledTwo); - assertTrue(scheduledOne.isEmpty()); - } - - @Test - public void testSelectForUpdateWithLockQueue() throws InterruptedException { - - hookDao.create(HookDaoImplTest.buildHook("partyId", "fake2.url")); - - InvoicingMessage message = BuildUtils - .buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "1", "partyId", EventType.INVOICE_CREATED, - InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED); - - messageDao.saveBatch(List.of(message)); - queueDao.saveBatchWithPolicies(List.of(message.getId())); - taskDao.save(List.of(message.getId())); - - Set scheduledOne = new HashSet<>(); - new Thread(() -> transactionTemplate.execute(tr -> { - scheduledOne.addAll(taskDao.getScheduled().values().stream().flatMap(List::stream) - .map(t -> t.getMessageId() + " " + t.getQueueId()).collect(Collectors.toSet())); - System.out.println("scheduledOne: " + scheduledOne); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return 1; - })).start(); - - Thread.sleep(100); - - assertEquals(2, scheduledOne.size()); - - Set scheduledTwo = new HashSet<>(); - new Thread(() -> transactionTemplate.execute(tr -> { - scheduledTwo.addAll(taskDao.getScheduled().values().stream().flatMap(List::stream) - .map(t -> t.getMessageId() + " " + t.getQueueId()).collect(Collectors.toSet())); - System.out.println("scheduledTwo :" + scheduledTwo); - return 1; - })).start(); - - Thread.sleep(1000); - - assertTrue(scheduledTwo.isEmpty()); - } - - @Test - public void testAvailabilityOrdering() throws InterruptedException { - - Hook hook1 = HookDaoImplTest.buildHook("partyId_1", "fake1.url"); - hookDao.create(hook1); - hookDao.updateAvailability(hookDao.getPartyHooks("partyId_1").get(0).getId(), 0.1); - InvoicingMessage message1 = BuildUtils - .buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "1", "partyId_1", EventType.INVOICE_CREATED, - InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED); - - Hook hook2 = HookDaoImplTest.buildHook("partyId_2", "fake2.url"); - hookDao.create(hook2); - InvoicingMessage message2 = BuildUtils - .buildMessage(InvoicingMessageEnum.INVOICE.getValue(), "2", "partyId_2", EventType.INVOICE_CREATED, - InvoiceStatusEnum.PAID, PaymentStatusEnum.CAPTURED); - - messageDao.saveBatch(List.of(message1, message2)); - queueDao.saveBatchWithPolicies(List.of(message1.getId(), message2.getId())); - taskDao.save(List.of(message1.getId(), message2.getId())); - - - Map > scheduledOne = new HashMap<>(); - new Thread(() -> transactionTemplate.execute(tr -> { - scheduledOne.putAll(taskDao.getScheduled()); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return 1; - })).start(); - - Thread.sleep(100); - - assertEquals(1, scheduledOne.entrySet().size()); - assertEquals(message2.getId().longValue(), scheduledOne.values().iterator().next().get(0).getMessageId()); - - - Map > scheduledTwo = new HashMap<>(); - new Thread(() -> transactionTemplate.execute(tr -> { - scheduledTwo.putAll(taskDao.getScheduled()); - try { - Thread.sleep(500); - } catch (InterruptedException e) { - e.printStackTrace(); - } - return 1; - })).start(); - - Thread.sleep(100); - - assertEquals(1, scheduledTwo.entrySet().size()); - assertEquals(message1.getId().longValue(), scheduledTwo.values().iterator().next().get(0).getMessageId()); - } - - @Test - public void removeAll() { - taskDao.removeAll(hookId); - } -} diff --git a/src/test/java/dev/vality/hooker/dao/MessageIdsGeneratorDaoImplTest.java b/src/test/java/dev/vality/hooker/dao/MessageIdsGeneratorDaoImplTest.java deleted file mode 100644 index 6aa15c9..0000000 --- a/src/test/java/dev/vality/hooker/dao/MessageIdsGeneratorDaoImplTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package dev.vality.hooker.dao; - -import dev.vality.hooker.AbstractIntegrationTest; -import dev.vality.hooker.dao.impl.MessageIdsGeneratorDaoImpl; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.List; - -import static org.junit.Assert.assertEquals; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class MessageIdsGeneratorDaoImplTest extends AbstractIntegrationTest { - - @Autowired - private MessageIdsGeneratorDaoImpl idsGeneratorDao; - - @Test - public void test() { - List list = idsGeneratorDao.get(100); - assertEquals(100, list.size()); - } -} diff --git a/src/test/java/dev/vality/hooker/dao/impl/CustomerTaskDaoTest.java b/src/test/java/dev/vality/hooker/dao/impl/CustomerTaskDaoTest.java deleted file mode 100644 index 6d4ce6d..0000000 --- a/src/test/java/dev/vality/hooker/dao/impl/CustomerTaskDaoTest.java +++ /dev/null @@ -1,80 +0,0 @@ -package dev.vality.hooker.dao.impl; - -import dev.vality.hooker.AbstractIntegrationTest; -import dev.vality.hooker.dao.HookDao; -import dev.vality.hooker.dao.HookDaoImplTest; -import dev.vality.hooker.model.CustomerMessageEnum; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.Task; -import dev.vality.hooker.utils.BuildUtils; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; -import org.springframework.test.context.junit4.SpringRunner; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.Assert.assertEquals; - -@RunWith(SpringRunner.class) -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class CustomerTaskDaoTest extends AbstractIntegrationTest { - - @Autowired - private CustomerTaskDao taskDao; - - @Autowired - private CustomerQueueDao queueDao; - - @Autowired - private HookDao hookDao; - - @Autowired - private NamedParameterJdbcTemplate jdbcTemplate; - - @Autowired - private CustomerDaoImpl customerDao; - - private Long messageId; - private Long hookId; - private String custId = "124"; - - @Before - public void setUp() throws Exception { - hookId = hookDao.create(HookDaoImplTest.buildCustomerHook("partyId", "fake.url")).getId(); - customerDao.create(BuildUtils - .buildCustomerMessage(1L, "partyId", EventType.CUSTOMER_CREATED, CustomerMessageEnum.CUSTOMER, custId, - "4356")); - messageId = customerDao.getAny(custId, CustomerMessageEnum.CUSTOMER).getId(); - } - - @After - public void after() throws Exception { - jdbcTemplate.update("truncate hook.scheduled_task, hook.customer_queue, hook.customer_message, " + - "hook.webhook_to_events, hook.webhook", new HashMap<>()); - } - - @Test - public void createDeleteGet() { - queueDao.createWithPolicy(messageId); - taskDao.create(messageId); - Map > scheduled = taskDao.getScheduled(); - assertEquals(1, scheduled.size()); - taskDao.remove(scheduled.keySet().iterator().next(), messageId); - assertEquals(0, taskDao.getScheduled().size()); - } - - @Test - public void testSaveWithHookIdAndCustomerId() { - queueDao.createWithPolicy(messageId); - int count = taskDao.create(hookId, custId); - assertEquals(1, count); - } - -} diff --git a/src/test/java/dev/vality/hooker/kafka/KafkaMachineEventListenerKafkaTest.java b/src/test/java/dev/vality/hooker/kafka/KafkaMachineEventListenerKafkaTest.java index 7c59088..e34dc7e 100644 --- a/src/test/java/dev/vality/hooker/kafka/KafkaMachineEventListenerKafkaTest.java +++ b/src/test/java/dev/vality/hooker/kafka/KafkaMachineEventListenerKafkaTest.java @@ -47,9 +47,6 @@ public class KafkaMachineEventListenerKafkaTest extends AbstractKafkaIntegration @org.springframework.beans.factory.annotation.Value("${kafka.topics.customer.id}") private String customerTopic; - @MockBean - private HandlerManager handlerManager; - @MockBean private MachineEventParser eventParser; @@ -102,7 +99,6 @@ public class KafkaMachineEventListenerKafkaTest extends AbstractKafkaIntegration Value data = new Value(); data.setBin(new byte[0]); message.setCreatedAt(LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME)); - message.setEventId(1L); message.setSourceNs(SOURCE_NS); message.setSourceId(SOURCE_ID); message.setData(data); diff --git a/src/test/java/dev/vality/hooker/listener/InvoicingMachineEventHandlerTest.java b/src/test/java/dev/vality/hooker/listener/InvoicingMachineEventHandlerTest.java index df3fd64..77309aa 100644 --- a/src/test/java/dev/vality/hooker/listener/InvoicingMachineEventHandlerTest.java +++ b/src/test/java/dev/vality/hooker/listener/InvoicingMachineEventHandlerTest.java @@ -4,9 +4,10 @@ import dev.vality.damsel.payment_processing.Event; import dev.vality.damsel.payment_processing.EventPayload; import dev.vality.damsel.payment_processing.InvoiceChange; import dev.vality.hooker.exception.ParseException; -import dev.vality.hooker.handler.poller.invoicing.AbstractInvoiceEventMapper; -import dev.vality.hooker.service.BatchService; +import dev.vality.hooker.handler.Mapper; +import dev.vality.hooker.model.InvoicingMessage; import dev.vality.hooker.service.HandlerManager; +import dev.vality.hooker.service.MessageService; import dev.vality.machinegun.eventsink.MachineEvent; import dev.vality.sink.common.parser.impl.MachineEventParser; import org.junit.Before; @@ -18,15 +19,14 @@ import org.springframework.kafka.support.Acknowledgment; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import static org.mockito.ArgumentMatchers.any; public class InvoicingMachineEventHandlerTest { @Mock - private HandlerManager handlerManager; - @Mock - private AbstractInvoiceEventMapper handler; + private Mapper handler; @Mock private MachineEventParser eventParser; @Mock @@ -34,18 +34,16 @@ public class InvoicingMachineEventHandlerTest { private InvoicingMachineEventHandler machineEventHandler; - private BatchService batchService; + private MessageService invoicingService; @Before public void init() { MockitoAnnotations.initMocks(this); - machineEventHandler = new InvoicingMachineEventHandler(handlerManager, eventParser, batchService); + machineEventHandler = new InvoicingMachineEventHandler(List.of(handler), eventParser, invoicingService); } @Test public void listenEmptyChanges() { - Mockito.when(handlerManager.getHandler(any())).thenReturn(java.util.Optional.of(handler)); - MachineEvent message = new MachineEvent(); Event event = new Event(); EventPayload payload = new EventPayload(); @@ -55,8 +53,7 @@ public class InvoicingMachineEventHandlerTest { machineEventHandler.handle(Collections.singletonList(message), ack); - Mockito.verify(handlerManager, Mockito.times(0)).getHandler(any()); - Mockito.verify(handler, Mockito.times(0)).handle(any(), any(), any()); + Mockito.verify(handler, Mockito.times(0)).map(any(), any()); Mockito.verify(ack, Mockito.times(1)).acknowledge(); } @@ -80,12 +77,10 @@ public class InvoicingMachineEventHandlerTest { MachineEvent message = new MachineEvent(); Mockito.when(eventParser.parse(message)).thenReturn(payload); - Mockito.when(handlerManager.getHandler(any())).thenReturn(java.util.Optional.of(handler)); machineEventHandler.handle(Collections.singletonList(message), ack); - Mockito.verify(handlerManager, Mockito.times(1)).getHandler(any()); - Mockito.verify(handler, Mockito.times(1)).handle(any(), any(), any()); + Mockito.verify(handler, Mockito.times(1)).accept(any()); Mockito.verify(ack, Mockito.times(1)).acknowledge(); } diff --git a/src/test/java/dev/vality/hooker/service/BatchProcessingTest.java b/src/test/java/dev/vality/hooker/service/BatchProcessingTest.java deleted file mode 100644 index a7b74a7..0000000 --- a/src/test/java/dev/vality/hooker/service/BatchProcessingTest.java +++ /dev/null @@ -1,248 +0,0 @@ -package dev.vality.hooker.service; - -import dev.vality.damsel.base.Content; -import dev.vality.damsel.domain.BankCard; -import dev.vality.damsel.domain.Cash; -import dev.vality.damsel.domain.ClientInfo; -import dev.vality.damsel.domain.ContactInfo; -import dev.vality.damsel.domain.CurrencyRef; -import dev.vality.damsel.domain.DisposablePaymentResource; -import dev.vality.damsel.domain.Invoice; -import dev.vality.damsel.domain.InvoiceCart; -import dev.vality.damsel.domain.InvoiceDetails; -import dev.vality.damsel.domain.InvoiceLine; -import dev.vality.damsel.domain.InvoicePayment; -import dev.vality.damsel.domain.InvoicePaymentFlow; -import dev.vality.damsel.domain.InvoicePaymentPending; -import dev.vality.damsel.domain.InvoicePaymentProcessed; -import dev.vality.damsel.domain.InvoicePaymentStatus; -import dev.vality.damsel.domain.InvoiceStatus; -import dev.vality.damsel.domain.InvoiceUnpaid; -import dev.vality.damsel.domain.LegacyBankCardPaymentSystem; -import dev.vality.damsel.domain.Payer; -import dev.vality.damsel.domain.PaymentResourcePayer; -import dev.vality.damsel.domain.PaymentTool; -import dev.vality.damsel.payment_processing.InvoiceChange; -import dev.vality.damsel.payment_processing.InvoiceCreated; -import dev.vality.damsel.payment_processing.InvoicePaymentChange; -import dev.vality.damsel.payment_processing.InvoicePaymentChangePayload; -import dev.vality.damsel.payment_processing.InvoicePaymentStarted; -import dev.vality.damsel.payment_processing.InvoicePaymentStatusChanged; -import dev.vality.hooker.AbstractIntegrationTest; -import dev.vality.hooker.dao.HookDao; -import dev.vality.hooker.dao.impl.InvoicingMessageDaoImpl; -import dev.vality.hooker.dao.impl.InvoicingQueueDao; -import dev.vality.hooker.dao.impl.InvoicingTaskDao; -import dev.vality.hooker.handler.poller.invoicing.AbstractInvoiceEventMapper; -import dev.vality.hooker.model.EventInfo; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.InvoicingMessageKey; -import dev.vality.hooker.model.PaymentStatusEnum; -import dev.vality.hooker.utils.BuildUtils; -import dev.vality.hooker.utils.KeyUtils; -import org.junit.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import javax.validation.constraints.NotNull; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Optional; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -public class BatchProcessingTest extends AbstractIntegrationTest { - - @Autowired - private HandlerManager handlerManager; - - @Autowired - private BatchService batchService; - - @Autowired - private InvoicingMessageDaoImpl messageDao; - - @Autowired - private InvoicingTaskDao taskDao; - - @Autowired - private InvoicingQueueDao invoicingQueueDao; - - @Autowired - private HookDao hookDao; - - @Test - public void testBatchProcess() { - hookDao.create(BuildUtils.buildHook("partyId", "www.kek.ru", EventType.INVOICE_CREATED)); - - LinkedHashMap storage = new LinkedHashMap<>(); - - InvoiceChange ic = getInvoiceCreated(); - EventInfo eventInfo = new EventInfo(null, "2016-03-22T06:12:27Z", "invoiceId", 1L, 1); - Optional eventMapperOptional = handlerManager.getHandler(ic); - assertTrue(eventMapperOptional.isPresent()); - AbstractInvoiceEventMapper invoiceEventMapper = eventMapperOptional.get(); - InvoicingMessage invoiceCreated = invoiceEventMapper.handle(ic, eventInfo, storage); - assertNotNull(invoiceCreated); - assertEquals("invoiceId", invoiceCreated.getInvoiceId()); - assertEquals(InvoicingMessageEnum.INVOICE, invoiceCreated.getType()); - storage.put(KeyUtils.key(invoiceCreated), invoiceCreated); - - InvoiceChange icPaymentStarted = getInvoicePaymentStarted(); - EventInfo eventInfoPaymentStarted = new EventInfo(null, "2016-03-22T06:12:27Z", "invoiceId", 1L, 2); - Optional eventMapperPaymentStartedOptional = - handlerManager.getHandler(icPaymentStarted); - assertTrue(eventMapperPaymentStartedOptional.isPresent()); - AbstractInvoiceEventMapper invoicePaymentStartedEventMapper = eventMapperPaymentStartedOptional.get(); - InvoicingMessage paymentStarted = - invoicePaymentStartedEventMapper.handle(icPaymentStarted, eventInfoPaymentStarted, storage); - assertNotNull(paymentStarted); - assertEquals(InvoicingMessageEnum.PAYMENT, paymentStarted.getType()); - assertEquals("partyId", paymentStarted.getPartyId()); - assertNotEquals(invoiceCreated.getChangeId(), paymentStarted.getChangeId()); - - List messages = new ArrayList<>(); - - storage.put(KeyUtils.key(invoiceCreated), invoiceCreated); - storage.put(KeyUtils.key(paymentStarted), paymentStarted); - messages.add(invoiceCreated); - messages.add(paymentStarted); - - assertEquals(2, storage.size()); - assertEquals(2, messages.size()); - - InvoiceChange icStatusChanged = getInvoicePaymentChangeStatus(); - EventInfo eventInfoPaymentStatusChanged = new EventInfo(null, "2016-03-22T06:12:27Z", "invoiceId", 1L, 3); - Optional eventMapperPaymentStatusChangedOptional = - handlerManager.getHandler(icStatusChanged); - assertTrue(eventMapperPaymentStatusChangedOptional.isPresent()); - AbstractInvoiceEventMapper invoicePaymentStatusChangedEventMapper = - eventMapperPaymentStatusChangedOptional.get(); - InvoicingMessage statusChanged = - invoicePaymentStatusChangedEventMapper.handle(icStatusChanged, eventInfoPaymentStatusChanged, storage); - assertNotNull(statusChanged); - assertEquals("partyId", statusChanged.getPartyId()); - assertEquals(PaymentStatusEnum.PROCESSED, statusChanged.getPaymentStatus()); - assertNotEquals(statusChanged.getPaymentStatus(), paymentStarted.getPaymentStatus()); - storage.put(KeyUtils.key(statusChanged), statusChanged); - messages.add(statusChanged); - - assertEquals(2, storage.size()); - assertEquals(3, messages.size()); - - // not found message - InvoiceChange icStatusNotFoundChanged = getInvoicePaymentChangeStatus(); - EventInfo eventInfoPaymentStatusNotFoundChanged = - new EventInfo(null, "2016-03-22T06:12:27Z", "not_found", 1L, 3); - Optional eventMapperPaymentStatusNotFoundChangedOptional = - handlerManager.getHandler(icStatusNotFoundChanged); - assertTrue(eventMapperPaymentStatusChangedOptional.isPresent()); - AbstractInvoiceEventMapper invoicePaymentStatusNotFoundChangedEventMapper = - eventMapperPaymentStatusNotFoundChangedOptional.get(); - InvoicingMessage statusNotFoundChanged = invoicePaymentStatusNotFoundChangedEventMapper - .handle(icStatusNotFoundChanged, eventInfoPaymentStatusNotFoundChanged, storage); - assertNull(statusNotFoundChanged); - - batchService.process(messages); - // - InvoicingMessage invoiceCreatedFromDB = messageDao.getInvoicingMessage(KeyUtils.key(invoiceCreated)); - assertNotNull(invoiceCreatedFromDB); - assertNotNull(invoiceCreatedFromDB.getId()); - assertNotNull(invoiceCreatedFromDB.getEventId()); - InvoicingMessage lastStateOfPayment = messageDao.getInvoicingMessage(KeyUtils.key(statusChanged)); - assertNotNull(lastStateOfPayment); - assertNotEquals(lastStateOfPayment.getId(), invoiceCreatedFromDB.getId()); - InvoicingMessage theSameLastStateOfPayment = messageDao.getInvoicingMessage(KeyUtils.key(paymentStarted)); - assertNotNull(theSameLastStateOfPayment); - Long messageId = theSameLastStateOfPayment.getId(); - assertEquals(messageId, lastStateOfPayment.getId()); - - assertNotEquals(messageDao.getBy(Collections.singletonList(messageId - 1)).get(0).getPaymentStatus(), - messageDao.getBy(Collections.singletonList(messageId)).get(0).getPaymentStatus()); - - assertEquals(1, taskDao.getScheduled().size()); - assertEquals(1, invoicingQueueDao.getWithPolicies(Collections.singletonList(1L)).size()); - - //test duplication - batchService.process(messages); - assertEquals(1, invoicingQueueDao.getWithPolicies(Collections.singletonList(1L)).size()); - } - - private InvoiceChange getInvoicePaymentStarted() { - InvoicePayment payment = new InvoicePayment() - .setId("1") - .setCreatedAt("2016-03-22T06:12:27Z") - .setStatus(InvoicePaymentStatus.pending(new InvoicePaymentPending())) - .setPayer(Payer.payment_resource( - new PaymentResourcePayer() - .setResource(new DisposablePaymentResource() - .setPaymentTool(PaymentTool.bank_card(new BankCard() - .setToken("token") - .setPaymentSystemDeprecated(LegacyBankCardPaymentSystem.amex) - .setBin("bin") - .setLastDigits("masked"))) - .setClientInfo(new ClientInfo())) - .setContactInfo(new ContactInfo()))) - .setCost(new Cash() - .setAmount(123L) - .setCurrency(new CurrencyRef() - .setSymbolicCode("RUB"))) - .setFlow(new InvoicePaymentFlow()); - - return InvoiceChange.invoice_payment_change( - new InvoicePaymentChange() - .setId("1") - .setPayload( - InvoicePaymentChangePayload.invoice_payment_started( - new InvoicePaymentStarted().setPayment(payment) - ))); - } - - - private InvoiceChange getInvoicePaymentChangeStatus() { - return InvoiceChange.invoice_payment_change( - new InvoicePaymentChange() - .setId("1") - .setPayload(InvoicePaymentChangePayload.invoice_payment_status_changed( - new InvoicePaymentStatusChanged() - .setStatus(InvoicePaymentStatus.processed(new InvoicePaymentProcessed()))))); - } - - @NotNull - private InvoiceChange getInvoiceCreated() { - InvoiceChange ic = new InvoiceChange(); - InvoiceCreated invoiceCreated = new InvoiceCreated(); - Invoice invoice = new Invoice(); - invoiceCreated.setInvoice( - invoice.setId("invoiceId") - .setOwnerId("partyId") - .setShopId("shopId") - .setCreatedAt("2016-03-22T06:12:27Z") - .setStatus(InvoiceStatus.unpaid(new InvoiceUnpaid())) - .setDetails(new InvoiceDetails() - .setProduct("product") - .setCart(new InvoiceCart() - .setLines(Arrays.asList( - new InvoiceLine() - .setQuantity(1) - .setProduct("product") - .setPrice(new Cash(1L, new CurrencyRef("RUB"))))))) - .setDue("2016-03-22T06:12:27Z") - .setCost(new Cash() - .setAmount(123L) - .setCurrency(new CurrencyRef() - .setSymbolicCode("RUB"))) - .setContext(new Content())); - ic.setInvoiceCreated(invoiceCreated); - return ic; - } -} diff --git a/src/test/java/dev/vality/hooker/service/CustomerEventServiceTest.java b/src/test/java/dev/vality/hooker/service/CustomerEventServiceTest.java index ff4edee..054447d 100644 --- a/src/test/java/dev/vality/hooker/service/CustomerEventServiceTest.java +++ b/src/test/java/dev/vality/hooker/service/CustomerEventServiceTest.java @@ -3,25 +3,26 @@ package dev.vality.hooker.service; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import dev.vality.damsel.payment_processing.CustomerManagementSrv; -import dev.vality.hooker.AbstractIntegrationTest; +import dev.vality.hooker.config.PostgresqlSpringBootITest; import dev.vality.hooker.model.CustomerMessage; import dev.vality.hooker.model.CustomerMessageEnum; import dev.vality.hooker.model.EventType; import dev.vality.hooker.utils.BuildUtils; import dev.vality.swag_webhook_events.model.CustomerBindingSucceeded; import dev.vality.swag_webhook_events.model.Event; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import static io.github.benas.randombeans.api.EnhancedRandom.random; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; -public class CustomerEventServiceTest extends AbstractIntegrationTest { +@PostgresqlSpringBootITest +public class CustomerEventServiceTest { @MockBean private CustomerManagementSrv.Iface customerClient; @@ -32,14 +33,14 @@ public class CustomerEventServiceTest extends AbstractIntegrationTest { @Autowired private ObjectMapper objectMapper; - @Before + @BeforeEach public void setUp() throws Exception { Mockito.when(customerClient.get(any(), any())) .thenReturn(BuildUtils.buildCustomer("customerId", "bindingId")); } @Test - public void testCustomerSucceeded() { + public void testCustomerSucceded() { CustomerMessage message = random(CustomerMessage.class); message.setType(CustomerMessageEnum.BINDING); message.setEventTime("2016-03-22T06:12:27Z"); @@ -48,7 +49,6 @@ public class CustomerEventServiceTest extends AbstractIntegrationTest { Event event = service.getEventByMessage(message); assertTrue(event instanceof CustomerBindingSucceeded); CustomerBindingSucceeded bindingSucceeded = (CustomerBindingSucceeded) event; - assertEquals(message.getEventId().intValue(), event.getEventID().intValue()); assertEquals("customerId", bindingSucceeded.getCustomer().getId()); assertEquals("bindingId", bindingSucceeded.getBinding().getId()); } diff --git a/src/test/java/dev/vality/hooker/service/HooksLimitServiceTest.java b/src/test/java/dev/vality/hooker/service/HooksLimitServiceTest.java index aeb8aef..30010cf 100644 --- a/src/test/java/dev/vality/hooker/service/HooksLimitServiceTest.java +++ b/src/test/java/dev/vality/hooker/service/HooksLimitServiceTest.java @@ -1,15 +1,11 @@ package dev.vality.hooker.service; -import dev.vality.damsel.webhooker.EventFilter; -import dev.vality.damsel.webhooker.InvoiceCreated; -import dev.vality.damsel.webhooker.InvoiceEventFilter; -import dev.vality.damsel.webhooker.InvoiceEventType; -import dev.vality.damsel.webhooker.WebhookParams; -import dev.vality.hooker.AbstractIntegrationTest; +import dev.vality.damsel.webhooker.*; +import dev.vality.hooker.config.PostgresqlSpringBootITest; import dev.vality.hooker.dao.HookDao; import dev.vality.hooker.utils.HookConverter; -import org.junit.After; -import org.junit.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; @@ -17,10 +13,11 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import java.util.Set; import java.util.stream.IntStream; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -public class HooksLimitServiceTest extends AbstractIntegrationTest { +@PostgresqlSpringBootITest +public class HooksLimitServiceTest { @Autowired private NamedParameterJdbcTemplate jdbcTemplate; @@ -68,7 +65,7 @@ public class HooksLimitServiceTest extends AbstractIntegrationTest { } - @After + @AfterEach public void after() { jdbcTemplate.update("truncate hook.webhook cascade", new MapSqlParameterSource()); jdbcTemplate.update("truncate hook.party_data cascade", new MapSqlParameterSource()); diff --git a/src/test/java/dev/vality/hooker/service/InvoicingEventServiceTest.java b/src/test/java/dev/vality/hooker/service/InvoicingEventServiceTest.java index b711d34..1a97e20 100644 --- a/src/test/java/dev/vality/hooker/service/InvoicingEventServiceTest.java +++ b/src/test/java/dev/vality/hooker/service/InvoicingEventServiceTest.java @@ -7,27 +7,24 @@ import dev.vality.damsel.domain.InvoicePaymentPending; import dev.vality.damsel.domain.InvoicePaymentStatus; import dev.vality.damsel.domain.InvoiceStatus; import dev.vality.damsel.payment_processing.InvoicingSrv; -import dev.vality.hooker.AbstractIntegrationTest; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.PaymentStatusEnum; -import dev.vality.hooker.model.RefundStatusEnum; +import dev.vality.hooker.config.PostgresqlSpringBootITest; +import dev.vality.hooker.model.*; import dev.vality.hooker.utils.BuildUtils; import dev.vality.swag_webhook_events.model.Event; import dev.vality.swag_webhook_events.model.RefundSucceeded; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.mock.mockito.MockBean; import static io.github.benas.randombeans.api.EnhancedRandom.random; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; -public class InvoicingEventServiceTest extends AbstractIntegrationTest { +@PostgresqlSpringBootITest +public class InvoicingEventServiceTest { @MockBean private InvoicingSrv.Iface invoicingClient; @@ -38,14 +35,12 @@ public class InvoicingEventServiceTest extends AbstractIntegrationTest { @Autowired private ObjectMapper objectMapper; - @Before + @BeforeEach public void setUp() throws Exception { Mockito.when(invoicingClient.get(any(), any(), any())) .thenReturn(BuildUtils.buildInvoice("partyId", "invoiceId", "1", "1", InvoiceStatus.paid(new InvoicePaid()), - InvoicePaymentStatus.pending( - new InvoicePaymentPending() - ))); + InvoicePaymentStatus.pending(new InvoicePaymentPending()))); } @Test @@ -60,7 +55,6 @@ public class InvoicingEventServiceTest extends AbstractIntegrationTest { Event event = service.getEventByMessage(message); assertTrue(event instanceof RefundSucceeded); RefundSucceeded refundSucceded = (RefundSucceeded) event; - assertEquals(message.getEventId().intValue(), event.getEventID().intValue()); assertEquals("invoiceId", refundSucceded.getInvoice().getId()); assertEquals("1", refundSucceded.getPayment().getId()); assertEquals("1", refundSucceded.getRefund().getId()); diff --git a/src/test/java/dev/vality/hooker/service/InvoicingMessageServiceTest.java b/src/test/java/dev/vality/hooker/service/InvoicingMessageServiceTest.java new file mode 100644 index 0000000..0047bf0 --- /dev/null +++ b/src/test/java/dev/vality/hooker/service/InvoicingMessageServiceTest.java @@ -0,0 +1,74 @@ +package dev.vality.hooker.service; + +import dev.vality.hooker.config.PostgresqlSpringBootITest; +import dev.vality.hooker.converter.WebhookMessageBuilder; +import dev.vality.hooker.dao.HookDao; +import dev.vality.hooker.model.EventType; +import dev.vality.hooker.model.InvoiceStatusEnum; +import dev.vality.hooker.model.InvoicingMessage; +import dev.vality.hooker.model.InvoicingMessageEnum; +import dev.vality.hooker.utils.BuildUtils; +import dev.vality.swag_webhook_events.model.Event; +import dev.vality.webhook.dispatcher.WebhookMessage; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; + +import static org.mockito.ArgumentMatchers.any; + +@PostgresqlSpringBootITest +public class InvoicingMessageServiceTest { + + @Autowired + private MessageService invoicingService; + + @Autowired + private HookDao hookDao; + + @MockBean + private InvoicingEventService invoicingMessageEventService; + + @MockBean + private WebhookMessageBuilder webhookMessageBuilder; + + @MockBean + private WebhookKafkaProducerService webhookKafkaProducerService; + + private static final String PARTY_ID = "partyId"; + + @BeforeEach + public void setUp() { + Mockito.when(invoicingMessageEventService.getEventByMessage(any())).thenReturn(new Event()); + Mockito.when(webhookMessageBuilder.build(any(), any(), any(), any())).thenReturn(new WebhookMessage()); + Mockito.doNothing().when(webhookKafkaProducerService).send(any()); + } + + @Test + public void testProcess() { + hookDao.create(BuildUtils.buildHook(PARTY_ID, "www.kek.ru", EventType.INVOICE_CREATED)); + hookDao.create(BuildUtils.buildHook(PARTY_ID, "www.lol.ru", EventType.INVOICE_CREATED)); + InvoicingMessage invoicingMessage = buildMessage(PARTY_ID, "invoice_id", + InvoicingMessageEnum.INVOICE, EventType.INVOICE_CREATED); + invoicingService.process(invoicingMessage); + Mockito.verify(invoicingMessageEventService, Mockito.times(1)).getEventByMessage(any()); + Mockito.verify(webhookMessageBuilder, Mockito.times(2)).build(any(), any(), any(), any()); + Mockito.verify(webhookKafkaProducerService, Mockito.times(2)).send(any()); + } + + private InvoicingMessage buildMessage(String partyId, String invoiceId, + InvoicingMessageEnum type, EventType eventType) { + InvoicingMessage invoicingMessage = new InvoicingMessage(); + invoicingMessage.setSequenceId(1L); + invoicingMessage.setChangeId(1); + invoicingMessage.setEventTime("2016-03-22T06:12:27Z"); + invoicingMessage.setSourceId(invoiceId); + invoicingMessage.setPartyId(partyId); + invoicingMessage.setShopId("shopId"); + invoicingMessage.setEventType(eventType); + invoicingMessage.setType(type); + invoicingMessage.setInvoiceStatus(InvoiceStatusEnum.UNPAID); + return invoicingMessage; + } +} diff --git a/src/test/java/dev/vality/hooker/service/PostSenderTest.java b/src/test/java/dev/vality/hooker/service/PostSenderTest.java deleted file mode 100644 index 0ac6c42..0000000 --- a/src/test/java/dev/vality/hooker/service/PostSenderTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package dev.vality.hooker.service; - -import okhttp3.HttpUrl; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class PostSenderTest { - - @Test - public void doPost() throws Exception { - PostSender postSender = new PostSender(1, 1); - MockWebServer server = new MockWebServer(); - HttpUrl httpUrl = server.url("/"); - - // happy case - server.enqueue(new MockResponse().setResponseCode(200).setBody("kek")); - int statusCode = postSender.doPost(httpUrl.toString(), 1, "kek", "kek"); - assertEquals(200, statusCode); - - // bad status code - server.enqueue(new MockResponse().setResponseCode(403).setBody("wrong")); - statusCode = postSender.doPost(httpUrl.toString(), 1, "kek", "kek"); - assertEquals(403, statusCode); - - // empty body - server.enqueue(new MockResponse().setResponseCode(301)); - statusCode = postSender.doPost(httpUrl.toString(), 1, "kek", "kek"); - assertEquals(301, statusCode); - - } -} diff --git a/src/test/java/dev/vality/hooker/utils/BuildUtils.java b/src/test/java/dev/vality/hooker/utils/BuildUtils.java index 8c48c02..79261f4 100644 --- a/src/test/java/dev/vality/hooker/utils/BuildUtils.java +++ b/src/test/java/dev/vality/hooker/utils/BuildUtils.java @@ -9,28 +9,12 @@ import dev.vality.geck.serializer.kit.mock.MockMode; import dev.vality.geck.serializer.kit.mock.MockTBaseProcessor; import dev.vality.geck.serializer.kit.tbase.TBaseHandler; import dev.vality.hooker.dao.WebhookAdditionalFilter; -import dev.vality.hooker.model.CustomerMessage; -import dev.vality.hooker.model.CustomerMessageEnum; -import dev.vality.hooker.model.EventType; -import dev.vality.hooker.model.Hook; -import dev.vality.hooker.model.InvoiceStatusEnum; -import dev.vality.hooker.model.InvoicingMessage; -import dev.vality.hooker.model.InvoicingMessageEnum; -import dev.vality.hooker.model.PaymentStatusEnum; -import dev.vality.hooker.model.RefundStatusEnum; +import dev.vality.hooker.model.*; import dev.vality.swag_webhook_events.model.Event; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - -import static io.github.benas.randombeans.api.EnhancedRandom.random; +import java.util.*; public class BuildUtils { private static int messageId = 1; @@ -44,13 +28,11 @@ public class BuildUtils { InvoiceStatusEnum invoiceStatus, PaymentStatusEnum paymentStatus, Long sequenceId, Integer changeId) { InvoicingMessage message = new InvoicingMessage(); - message.setId((long) messageId++); - message.setEventId((long) messageId++); message.setEventTime("2016-03-22T06:12:27Z"); message.setType(InvoicingMessageEnum.lookup(type)); message.setPartyId(partyId); message.setEventType(eventType); - message.setInvoiceId(invoiceId); + message.setSourceId(invoiceId); message.setShopId("123"); message.setInvoiceStatus(invoiceStatus); if (message.isPayment() || message.isRefund()) { @@ -84,37 +66,23 @@ public class BuildUtils { .setMetadata(Value.obj(new HashMap<>())) .setBindings(Collections.singletonList(customerBinding)); - BankCard bankCard = new BankCard() - .setPaymentSystem( - new PaymentSystemRef(random(LegacyBankCardPaymentSystem.class).name()) - ) - .setPaymentToken( - new BankCardTokenServiceRef(random(LegacyBankCardTokenProvider.class).name()) - ); customer.getBindings().get(0).getPaymentResource().setPaymentTool( - PaymentTool.bank_card(thriftBaseProcessor.process(bankCard, new TBaseHandler<>(BankCard.class)))); + PaymentTool.bank_card(thriftBaseProcessor.process(new BankCard(), new TBaseHandler<>(BankCard.class)))); return customer; } public static dev.vality.damsel.payment_processing.Invoice buildInvoice(String partyId, String invoiceId, - String paymentId, String refundId, - InvoiceStatus invoiceStatus, - InvoicePaymentStatus paymentStatus) + String paymentId, String refundId, + InvoiceStatus invoiceStatus, + InvoicePaymentStatus paymentStatus) throws IOException { MockTBaseProcessor thriftBaseProcessor = new MockTBaseProcessor(MockMode.RANDOM, 15, 1); dev.vality.damsel.payment_processing.Invoice invoice = new dev.vality.damsel.payment_processing.Invoice() .setInvoice(buildInvoice(partyId, invoiceId, invoiceStatus, thriftBaseProcessor)) .setPayments(buildPayments(partyId, paymentId, refundId, paymentStatus, thriftBaseProcessor)); if (invoice.getPayments().get(0).getPayment().getPayer().isSetPaymentResource()) { - BankCard bankCard = new BankCard() - .setPaymentSystem( - new PaymentSystemRef(random(LegacyBankCardPaymentSystem.class).name()) - ) - .setPaymentToken( - new BankCardTokenServiceRef(random(LegacyBankCardTokenProvider.class).name()) - ); PaymentTool paymentTool = PaymentTool.bank_card( - thriftBaseProcessor.process(bankCard, new TBaseHandler<>(BankCard.class)) + thriftBaseProcessor.process(new BankCard(), new TBaseHandler<>(BankCard.class)) ); invoice.getPayments().get(0).getPayment().getPayer().getPaymentResource().getResource() .setPaymentTool(paymentTool); @@ -125,9 +93,9 @@ public class BuildUtils { private static Invoice buildInvoice(String partyId, String invoiceId, InvoiceStatus invoiceStatus, MockTBaseProcessor thriftBaseProcessor) throws IOException { return thriftBaseProcessor.process( - new Invoice(), - new TBaseHandler<>(Invoice.class) - ) + new Invoice(), + new TBaseHandler<>(Invoice.class) + ) .setId(invoiceId) .setOwnerId(partyId) .setCreatedAt("2016-03-22T06:12:27Z") @@ -149,13 +117,13 @@ public class BuildUtils { } private static dev.vality.damsel.domain.InvoicePayment buildPayment(String partyId, String paymentId, - InvoicePaymentStatus paymentStatus, - MockTBaseProcessor thriftBaseProcessor) + InvoicePaymentStatus paymentStatus, + MockTBaseProcessor thriftBaseProcessor) throws IOException { return thriftBaseProcessor.process( - new dev.vality.damsel.domain.InvoicePayment(), - new TBaseHandler<>(dev.vality.damsel.domain.InvoicePayment.class) - ) + new dev.vality.damsel.domain.InvoicePayment(), + new TBaseHandler<>(dev.vality.damsel.domain.InvoicePayment.class) + ) .setCreatedAt("2016-03-22T06:12:27Z") .setId(paymentId) .setOwnerId(partyId) @@ -179,9 +147,9 @@ public class BuildUtils { MockTBaseProcessor thriftBaseProcessor ) throws IOException { return thriftBaseProcessor.process( - new InvoicePaymentRefund(), - new TBaseHandler<>(InvoicePaymentRefund.class) - ) + new InvoicePaymentRefund(), + new TBaseHandler<>(InvoicePaymentRefund.class) + ) .setReason("keksik") .setCreatedAt("2016-03-22T06:12:27Z") .setId(refundId); @@ -202,12 +170,11 @@ public class BuildUtils { public static CustomerMessage buildCustomerMessage(Long eventId, String partyId, EventType eventType, CustomerMessageEnum type, String custId, String shopId) { CustomerMessage customerMessage = new CustomerMessage(); - customerMessage.setEventId(eventId); customerMessage.setPartyId(partyId); customerMessage.setEventTime("2018-03-22T06:12:27Z"); customerMessage.setEventType(eventType); customerMessage.setType(type); - customerMessage.setCustomerId(custId); + customerMessage.setSourceId(custId); customerMessage.setShopId(shopId); if (customerMessage.isBinding()) { diff --git a/src/test/java/dev/vality/hooker/utils/CashFlowUtilsTest.java b/src/test/java/dev/vality/hooker/utils/CashFlowUtilsTest.java index 0a2fb28..7d1db4c 100644 --- a/src/test/java/dev/vality/hooker/utils/CashFlowUtilsTest.java +++ b/src/test/java/dev/vality/hooker/utils/CashFlowUtilsTest.java @@ -1,11 +1,6 @@ package dev.vality.hooker.utils; -import dev.vality.damsel.domain.Cash; -import dev.vality.damsel.domain.CashFlowAccount; -import dev.vality.damsel.domain.FinalCashFlowAccount; -import dev.vality.damsel.domain.FinalCashFlowPosting; -import dev.vality.damsel.domain.MerchantCashFlowAccount; -import dev.vality.damsel.domain.SystemCashFlowAccount; +import dev.vality.damsel.domain.*; import org.junit.Assert; import org.junit.Test; diff --git a/src/test/java/dev/vality/hooker/utils/PaymentToolUtilsTest.java b/src/test/java/dev/vality/hooker/utils/PaymentToolUtilsTest.java index bfb74a8..9ed7cdc 100644 --- a/src/test/java/dev/vality/hooker/utils/PaymentToolUtilsTest.java +++ b/src/test/java/dev/vality/hooker/utils/PaymentToolUtilsTest.java @@ -15,7 +15,6 @@ import org.junit.jupiter.api.Test; import java.io.IOException; -import static io.github.benas.randombeans.api.EnhancedRandom.random; import static org.junit.jupiter.api.Assertions.*; public class PaymentToolUtilsTest { @@ -31,7 +30,6 @@ public class PaymentToolUtilsTest { ((PaymentToolDetailsCryptoWallet) paymentToolDetails).getCryptoCurrency().getValue()); } - //TODO Bump swag-webhook-events @Test public void testDigitalWalletJson() throws JsonProcessingException { PaymentTool paymentTool = @@ -71,18 +69,11 @@ public class PaymentToolUtilsTest { @Test public void testGetPaymentToolDetailsBankCard() throws IOException { PaymentTool paymentTool = PaymentTool.bank_card(new MockTBaseProcessor(MockMode.RANDOM, 15, 2) - .process(new BankCard() - .setPaymentSystem( - new PaymentSystemRef(random(LegacyBankCardPaymentSystem.class).name()) - ) - .setPaymentToken( - new BankCardTokenServiceRef(random(LegacyBankCardTokenProvider.class).name()) - ), - new TBaseHandler<>(BankCard.class))); + .process(new BankCard(), new TBaseHandler<>(BankCard.class))); PaymentToolDetails paymentToolDetails = PaymentToolUtils.getPaymentToolDetails(paymentTool); assertTrue(paymentToolDetails instanceof PaymentToolDetailsBankCard); assertNotNull(paymentToolDetails.getDetailsType()); assertEquals(paymentTool.getBankCard().getBin(), ((PaymentToolDetailsBankCard) paymentToolDetails).getBin()); } -} \ No newline at end of file +}