Skip to content

Commit abfbe8e

Browse files
committed
MODLD-686: working proto
1 parent 960987b commit abfbe8e

File tree

10 files changed

+196
-36
lines changed

10 files changed

+196
-36
lines changed

src/main/java/org/folio/linked/data/configuration/kafka/KafkaListenerConfiguration.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
import java.util.Map;
1010
import lombok.RequiredArgsConstructor;
1111
import org.apache.kafka.common.serialization.StringDeserializer;
12-
import org.folio.linked.data.domain.dto.InventoryDomainEvent;
12+
import org.folio.linked.data.domain.dto.InventoryDomainHoldingEvent;
13+
import org.folio.linked.data.domain.dto.InventoryDomainItemEvent;
1314
import org.folio.linked.data.domain.dto.InventoryInstanceEvent;
1415
import org.folio.linked.data.domain.dto.SourceRecordDomainEvent;
1516
import org.folio.spring.tools.kafka.FolioKafkaProperties;
@@ -63,10 +64,27 @@ public ConsumerFactory<String, InventoryInstanceEvent> inventoryInstanceEventCon
6364
}
6465

6566
@Bean
66-
public ConcurrentKafkaListenerContainerFactory<String, InventoryDomainEvent> inventoryDomainEventListenerFactory(
67-
ConsumerFactory<String, InventoryDomainEvent> inventoryDomainEventListenerFactory
67+
public ConsumerFactory<String, InventoryDomainHoldingEvent> holdingEventConsumerFactory() {
68+
return errorHandlingConsumerFactory(InventoryDomainHoldingEvent.class);
69+
}
70+
71+
@Bean
72+
public ConcurrentKafkaListenerContainerFactory<String, InventoryDomainHoldingEvent> holdingListenerFactory(
73+
ConsumerFactory<String, InventoryDomainHoldingEvent> inventoryDomainEventConsumerFactory
74+
) {
75+
return concurrentKafkaBatchListenerContainerFactory(inventoryDomainEventConsumerFactory);
76+
}
77+
78+
@Bean
79+
public ConsumerFactory<String, InventoryDomainItemEvent> itemEventConsumerFactory() {
80+
return errorHandlingConsumerFactory(InventoryDomainItemEvent.class);
81+
}
82+
83+
@Bean
84+
public ConcurrentKafkaListenerContainerFactory<String, InventoryDomainItemEvent> itemListenerFactory(
85+
ConsumerFactory<String, InventoryDomainItemEvent> inventoryDomainEventConsumerFactory
6886
) {
69-
return concurrentKafkaBatchListenerContainerFactory(inventoryDomainEventListenerFactory);
87+
return concurrentKafkaBatchListenerContainerFactory(inventoryDomainEventConsumerFactory);
7088
}
7189

7290
private <K, V> ConcurrentKafkaListenerContainerFactory<K, V> concurrentKafkaBatchListenerContainerFactory(

src/main/java/org/folio/linked/data/integration/kafka/listener/InventoryDomainEventListener.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import lombok.RequiredArgsConstructor;
77
import lombok.extern.log4j.Log4j2;
88
import org.apache.kafka.clients.consumer.ConsumerRecord;
9-
import org.folio.linked.data.domain.dto.InventoryDomainEvent;
9+
import org.folio.linked.data.domain.dto.InventoryDomainHoldingEvent;
10+
import org.folio.linked.data.domain.dto.InventoryDomainItemEvent;
1011
import org.springframework.context.annotation.Profile;
1112
import org.springframework.kafka.annotation.KafkaListener;
1213
import org.springframework.stereotype.Component;
@@ -22,26 +23,26 @@ public class InventoryDomainEventListener {
2223

2324
@KafkaListener(
2425
id = ITEM_DOMAIN_EVENT_LISTENER,
25-
containerFactory = "inventoryDomainEventListenerFactory",
26+
containerFactory = "itemListenerFactory",
2627
groupId = "#{folioKafkaProperties.listener['inventory-item-domain-event'].groupId}",
2728
concurrency = "#{folioKafkaProperties.listener['inventory-item-domain-event'].concurrency}",
2829
topicPattern = "#{folioKafkaProperties.listener['inventory-item-domain-event'].topicPattern}")
29-
public void handleInventoryItemDomainEvent(List<ConsumerRecord<String, InventoryDomainEvent>> consumerRecords) {
30+
public void handleInventoryItemDomainEvent(List<ConsumerRecord<String, InventoryDomainItemEvent>> consumerRecords) {
3031
consumerRecords.forEach(cr -> processRecord(cr, "Item"));
3132
}
3233

3334
@KafkaListener(
3435
id = HOLDING_DOMAIN_EVENT_LISTENER,
35-
containerFactory = "inventoryDomainEventListenerFactory",
36+
containerFactory = "holdingListenerFactory",
3637
groupId = "#{folioKafkaProperties.listener['inventory-holding-domain-event'].groupId}",
3738
concurrency = "#{folioKafkaProperties.listener['inventory-holding-domain-event'].concurrency}",
3839
topicPattern = "#{folioKafkaProperties.listener['inventory-holding-domain-event'].topicPattern}")
39-
public void handleInventoryHoldingDomainEvent(List<ConsumerRecord<String, InventoryDomainEvent>> consumerRecords) {
40+
public void handleInventoryHoldingDomainEvent(List<ConsumerRecord<String, InventoryDomainHoldingEvent>> consumerRecords) {
4041
consumerRecords.forEach(cr -> processRecord(cr, "Holding"));
4142
}
4243

43-
private void processRecord(ConsumerRecord<String, InventoryDomainEvent> event, String entityType) {
44-
log.info("Received [{}] Domain Event: [key {}], value [{}]", entityType, event.key(), event.value());
44+
private void processRecord(Object event, String entityType) {
45+
log.info("Received [{}] Domain Event: {}", entityType, event);
4546
}
4647

4748
}

src/main/resources/swagger.api/folio-modules.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,7 @@ components:
2626
$ref: folio-modules/srs/sourceRecordDomainEvent.json
2727
inventoryInstanceEvent:
2828
$ref: folio-modules/inventory/inventoryInstanceEvent.json
29-
inventoryDomainEvent:
30-
$ref: folio-modules/inventory/storage/inventoryDomainEvent.json
29+
inventoryDomainHoldingEvent:
30+
$ref: folio-modules/inventory/storage/inventoryDomainHoldingEvent.json
31+
inventoryDomainItemEvent:
32+
$ref: folio-modules/inventory/storage/inventoryDomainItemEvent.json

src/main/resources/swagger.api/folio-modules/inventory/storage/inventoryDomainEventPayload.json

Lines changed: 0 additions & 17 deletions
This file was deleted.

src/main/resources/swagger.api/folio-modules/inventory/storage/inventoryDomainEvent.json renamed to src/main/resources/swagger.api/folio-modules/inventory/storage/inventoryDomainHoldingEvent.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "http://json-schema.org/draft-04/schema#",
3-
"description": "Inventory domain event data model",
3+
"description": "Inventory Holding domain event data model",
44
"type": "object",
55
"additionalProperties": false,
66
"properties": {
@@ -12,13 +12,13 @@
1212
"description": "Event timestamp",
1313
"type": "string"
1414
},
15-
"oldEntity": {
15+
"old": {
1616
"description": "Old entity",
17-
"$ref": "inventoryDomainEventPayload.json"
17+
"$ref": "holdingsRecord.json"
1818
},
19-
"newEntity": {
19+
"new": {
2020
"description": "New entity",
21-
"$ref": "inventoryDomainEventPayload.json"
21+
"$ref": "holdingsRecord.json"
2222
},
2323
"type": {
2424
"type": "string",
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema#",
3+
"description": "Inventory Item domain event data model",
4+
"type": "object",
5+
"additionalProperties": false,
6+
"properties": {
7+
"eventId": {
8+
"description": "UUID",
9+
"$ref": "../../common/uuid.json"
10+
},
11+
"eventTs": {
12+
"description": "Event timestamp",
13+
"type": "string"
14+
},
15+
"old": {
16+
"description": "Old entity",
17+
"$ref": "inventoryItem.json"
18+
},
19+
"new": {
20+
"description": "New entity",
21+
"$ref": "inventoryItem.json"
22+
},
23+
"type": {
24+
"type": "string",
25+
"enum": [
26+
"UPDATE",
27+
"DELETE",
28+
"CREATE",
29+
"DELETE_ALL",
30+
"REINDEX",
31+
"ITERATE",
32+
"MIGRATION"
33+
],
34+
"description": "Inventory domain event type"
35+
},
36+
"eventMetadata": {
37+
"type": "object",
38+
"$ref": "../../common/eventMetadata.json",
39+
"description": "Event metadata"
40+
},
41+
"tenant": {
42+
"type": "string",
43+
"description": "Tenant id"
44+
}
45+
},
46+
"excludedFromEqualsAndHashCode": [
47+
"eventMetadata"
48+
],
49+
"required": [
50+
"id",
51+
"eventType"
52+
]
53+
}

src/test/java/org/folio/linked/data/integration/kafka/listener/InventoryDomainEventListenerIT.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
package org.folio.linked.data.integration.kafka.listener;
22

33
import static org.folio.linked.data.test.TestUtil.TENANT_ID;
4+
import static org.folio.linked.data.test.TestUtil.awaitAndAssert;
45
import static org.folio.linked.data.test.kafka.KafkaEventsTestDataFixture.getInventoryDomainEventHoldingSampleProducerRecord;
56
import static org.folio.linked.data.test.kafka.KafkaEventsTestDataFixture.getInventoryDomainEventItemSampleProducerRecord;
7+
import static org.mockito.ArgumentMatchers.any;
8+
import static org.mockito.Mockito.verify;
69

710
import org.folio.linked.data.e2e.base.IntegrationTest;
811
import org.folio.spring.tools.kafka.KafkaAdminService;
912
import org.junit.jupiter.api.BeforeAll;
1013
import org.junit.jupiter.api.Test;
1114
import org.springframework.beans.factory.annotation.Autowired;
1215
import org.springframework.kafka.core.KafkaTemplate;
16+
import org.springframework.test.context.bean.override.mockito.MockitoSpyBean;
1317

1418
@IntegrationTest
1519
class InventoryDomainEventListenerIT {
1620

1721
@Autowired
1822
private KafkaTemplate<String, String> eventKafkaTemplate;
23+
@MockitoSpyBean
24+
private InventoryDomainEventListener inventoryDomainEventListener;
1925

2026
@BeforeAll
2127
static void setup(@Autowired KafkaAdminService kafkaAdminService) {
@@ -43,7 +49,7 @@ void shouldHandleHoldingDomainEvent() {
4349
eventKafkaTemplate.send(eventProducerRecord);
4450

4551
// then
46-
// check logs, that's enough for Spike
52+
awaitAndAssert(() -> verify(inventoryDomainEventListener).handleInventoryHoldingDomainEvent(any()));
4753
}
4854

4955
}

src/test/resources/application-test.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ folio:
1818
num-partitions: 1
1919
- name: inventory.instance
2020
num-partitions: 1
21+
- name: inventory.item
22+
num-partitions: 1
23+
- name: inventory.holdings-record
24+
num-partitions: 1
2125

2226
mod-linked-data:
2327
reindex:
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"new": {
3+
"id": "d48996b4-170e-43e4-8f4d-cafaa75e7b52",
4+
"_version": 1,
5+
"sourceId": "f32d531e-df79-46b3-8932-cdd35f7a2264",
6+
"hrid": "oho00056184712",
7+
"formerIds": [],
8+
"instanceId": "c1ef011b-f97e-4ed0-aec3-636cd2f64107",
9+
"permanentLocationId": "574326a1-f240-4222-82b3-21ccd6d6e5e5",
10+
"effectiveLocationId": "574326a1-f240-4222-82b3-21ccd6d6e5e5",
11+
"electronicAccess": [],
12+
"callNumberTypeId": "95467209-6d7b-468b-94df-0f5d7ad2747d",
13+
"callNumber": "1986",
14+
"administrativeNotes": [],
15+
"notes": [],
16+
"holdingsStatements": [],
17+
"holdingsStatementsForIndexes": [],
18+
"holdingsStatementsForSupplements": [],
19+
"statisticalCodeIds": [],
20+
"metadata": {
21+
"createdDate": "2025-04-11T11:39:26.882+00:00",
22+
"createdByUserId": "cee695b3-8732-447c-90d2-534f1fa16991",
23+
"updatedDate": "2025-04-11T11:39:26.882+00:00",
24+
"updatedByUserId": "cee695b3-8732-447c-90d2-534f1fa16991"
25+
}
26+
},
27+
"type": "CREATE",
28+
"tenant": "fs09000000",
29+
"eventId": "38daa6bb-76cc-4492-a1de-80f3a4728182",
30+
"eventTs": 1744371567012
31+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
{
2+
"new": {
3+
"instanceId": "c1ef011b-f97e-4ed0-aec3-636cd2f64107",
4+
"id": "bafdd67b-f8f5-45e7-971a-8ab0fb76b03a",
5+
"_version": 1,
6+
"hrid": "oit00160053757",
7+
"holdingsRecordId": "d48996b4-170e-43e4-8f4d-cafaa75e7b52",
8+
"formerIds": [],
9+
"displaySummary": "Enum display summary",
10+
"barcode": "Barcode",
11+
"effectiveShelvingOrder": "41509 VOLUME VALUE ENUMERATION VALUE CHRONOLOGY VALUE",
12+
"itemLevelCallNumber": "1509",
13+
"effectiveCallNumberComponents": {
14+
"callNumber": "1509",
15+
"typeId": "95467209-6d7b-468b-94df-0f5d7ad2747d"
16+
},
17+
"volume": "Volume value",
18+
"enumeration": "Enumeration value",
19+
"chronology": "Chronology value",
20+
"yearCaption": [
21+
"Year, caption"
22+
],
23+
"itemDamagedStatusId": "516b82eb-1f19-4a63-8c48-8f1a3e9ff311",
24+
"itemDamagedStatusDate": "2025-04-11",
25+
"administrativeNotes": [],
26+
"notes": [
27+
{
28+
"itemNoteTypeId": "f618d7d8-0ab2-40ed-b76a-9a6cff141643",
29+
"note": "Action note",
30+
"staffOnly": false
31+
},
32+
{
33+
"itemNoteTypeId": "2864ca78-7d78-4a90-8ff6-13a4e30128b4",
34+
"note": "Note",
35+
"staffOnly": false
36+
}
37+
],
38+
"circulationNotes": [],
39+
"status": {
40+
"name": "Available",
41+
"date": "2025-04-11T11:44:08.630+00:00"
42+
},
43+
"materialTypeId": "025ba2c5-5e96-4667-a677-8186463aee69",
44+
"permanentLoanTypeId": "668c4500-fc4e-4140-8a9f-872b54f5ef31",
45+
"effectiveLocationId": "574326a1-f240-4222-82b3-21ccd6d6e5e5",
46+
"electronicAccess": [],
47+
"statisticalCodeIds": [],
48+
"tags": {
49+
"tagList": []
50+
},
51+
"metadata": {
52+
"createdDate": "2025-04-11T11:44:08.629+00:00",
53+
"createdByUserId": "cee695b3-8732-447c-90d2-534f1fa16991",
54+
"updatedDate": "2025-04-11T11:44:08.629+00:00",
55+
"updatedByUserId": "cee695b3-8732-447c-90d2-534f1fa16991"
56+
}
57+
},
58+
"type": "CREATE",
59+
"tenant": "fs09000000",
60+
"eventId": "ae3aa2db-c71a-4a32-83d7-3d7534178f5a",
61+
"eventTs": 1744371848744
62+
}

0 commit comments

Comments
 (0)