刘光辉
9 小时以前 06f314545ac3514d7ce28939920866ae8188d31c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package jnpf.message.mapper;
 
import jnpf.message.entity.MessageReceiveEntity;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.*;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
import static org.junit.jupiter.api.Assertions.*;
 
@EnabledIfEnvironmentVariable(named="DMS_READ_TEST_URL", matches=".+")
class DmsUpgradeMessagePostgresTest {
    @Test void receiptAndInboxRollbackTogetherAndDeduplicateAfterLostAcknowledgement() throws Exception {
        var ds=new UnpooledDataSource("org.postgresql.Driver",System.getenv("DMS_READ_TEST_URL"),System.getenv("DMS_READ_TEST_USER"),System.getenv("DMS_READ_TEST_PASSWORD"));
        var config=new Configuration(new Environment("message-test",new JdbcTransactionFactory(),ds));
        String path="mapper/DmsUpgradeMessageMapper.xml";
        try(var input=getClass().getResourceAsStream("/"+path)) {
            String xml=new String(Objects.requireNonNull(input).readAllBytes(),StandardCharsets.UTF_8).replace("public.","pg_temp.");
            new XMLMapperBuilder(new StringReader(xml),config,path,config.getSqlFragments()).parse();
        }
        try(var session=new SqlSessionFactoryBuilder().build(config).openSession(false)) {
            try {
                var c=session.getConnection();
                try(var sql=c.createStatement()) {
                    sql.execute("CREATE TEMP TABLE base_msg_template (LIKE public.base_msg_template INCLUDING DEFAULTS) ON COMMIT DROP");
                    sql.execute("CREATE TEMP TABLE base_message (LIKE public.base_message INCLUDING DEFAULTS INCLUDING INDEXES) ON COMMIT DROP");
                    sql.execute("CREATE TEMP TABLE dms_template_upgrade_message_receipts (tenant_id text,task_id text,user_id text,created_at timestamp default CURRENT_TIMESTAMP,PRIMARY KEY(tenant_id,task_id,user_id)) ON COMMIT DROP");
                    sql.execute("INSERT INTO pg_temp.base_msg_template(f_id,f_tenant_id,f_en_code,f_message_type,f_message_source,f_enabled_mark,f_title,f_content) VALUES ('template','test','dmsTemplateUpgrade','1','3',1,'title','body')");
                }
                var mapper=session.getMapper(DmsUpgradeMessageMapper.class);
                assertEquals("body",mapper.templates("test").getFirst().getContent()); assertTrue(mapper.templates("other").isEmpty());
                var savepoint=c.setSavepoint();
                assertEquals(1,mapper.claimDelivery("test","task","user"));
                var message=new MessageReceiveEntity(); message.setId("m1");message.setUserId("user");message.setTitle("title");message.setBodyText("body");
                assertEquals(1,mapper.insertMessage(message,"test"));
                assertThrows(Exception.class,()->mapper.insertMessage(message,"test"));
                c.rollback(savepoint);session.clearCache();
                assertEquals(1,mapper.claimDelivery("test","task","user"));
                assertEquals(1,mapper.insertMessage(message,"test"));
                assertEquals(0,mapper.claimDelivery("test","task","user"));
                assertEquals(1,mapper.claimDelivery("test","next-upgrade","user"));
                assertEquals(1,mapper.claimDelivery("other","task","user"));
                try(var sql=c.createStatement();var rows=sql.executeQuery("SELECT count(*) FROM pg_temp.base_message")) { assertTrue(rows.next());assertEquals(1,rows.getInt(1)); }
            } finally { session.rollback(true); }
        }
    }
    @Test void serviceTransactionRollsBackAllRecipientsAndAcknowledgesOnlyCommittedMessages() throws Exception {
        try(var c=java.sql.DriverManager.getConnection(System.getenv("DMS_READ_TEST_URL"),System.getenv("DMS_READ_TEST_USER"),System.getenv("DMS_READ_TEST_PASSWORD"));
            var pushes=org.mockito.Mockito.mockStatic(jnpf.message.util.PushMessageUtil.class)) {
            var ds=new org.springframework.jdbc.datasource.SingleConnectionDataSource(c,true);
            var config=new Configuration(new Environment("message-service-test",new org.mybatis.spring.transaction.SpringManagedTransactionFactory(),ds));
            String path="mapper/DmsUpgradeMessageMapper.xml";
            try(var input=getClass().getResourceAsStream("/"+path)) {
                String xml=new String(Objects.requireNonNull(input).readAllBytes(),StandardCharsets.UTF_8).replace("public.","pg_temp.");
                new XMLMapperBuilder(new StringReader(xml),config,path,config.getSqlFragments()).parse();
            }
            try(var sql=c.createStatement()) {
                sql.execute("CREATE TEMP TABLE base_msg_template (LIKE public.base_msg_template INCLUDING DEFAULTS)");
                sql.execute("CREATE TEMP TABLE base_message (LIKE public.base_message INCLUDING DEFAULTS INCLUDING INDEXES)");
                sql.execute("ALTER TABLE pg_temp.base_message ADD CONSTRAINT test_failure CHECK(f_user_id != 'fail')");
                sql.execute("CREATE TEMP TABLE dms_template_upgrade_message_receipts (tenant_id text,task_id text,user_id text,created_at timestamp default CURRENT_TIMESTAMP,PRIMARY KEY(tenant_id,task_id,user_id))");
                sql.execute("INSERT INTO pg_temp.base_msg_template(f_id,f_tenant_id,f_en_code,f_message_type,f_message_source,f_enabled_mark,f_title,f_content) VALUES ('template','test','dmsTemplateUpgrade','1','3',1,'title','body')");
            }
            var session=new org.mybatis.spring.SqlSessionTemplate(new SqlSessionFactoryBuilder().build(config));
            var target=new jnpf.message.service.DmsUpgradeMessageService(session.getMapper(DmsUpgradeMessageMapper.class));
            var proxy=new org.springframework.aop.framework.ProxyFactory(target);
            proxy.addAdvice(new org.springframework.transaction.interceptor.TransactionInterceptor(
                new org.springframework.jdbc.datasource.DataSourceTransactionManager(ds),new org.springframework.transaction.annotation.AnnotationTransactionAttributeSource()));
            var service=(jnpf.message.service.DmsUpgradeMessageService)proxy.getProxy();
            var request=new jnpf.message.model.DmsUpgradeMessage();request.setTenantId("test");request.setTaskId("task");request.setActorId("actor");
            request.setToUserIds(java.util.List.of("user","fail"));
            assertThrows(Exception.class,()->service.send(request));
            pushes.verifyNoInteractions();
            try(var sql=c.createStatement();var rows=sql.executeQuery("SELECT (SELECT count(*) FROM pg_temp.base_message)+(SELECT count(*) FROM pg_temp.dms_template_upgrade_message_receipts)")) {
                assertTrue(rows.next());assertEquals(0,rows.getInt(1));
            }
            request.setToUserIds(java.util.List.of("user")); assertTrue(service.send(request)); assertTrue(service.send(request));
            pushes.verify(()->jnpf.message.util.PushMessageUtil.pushMessage(org.mockito.ArgumentMatchers.anyMap(),org.mockito.ArgumentMatchers.any(),org.mockito.ArgumentMatchers.eq(3)),org.mockito.Mockito.times(1));
            try(var sql=c.createStatement();var rows=sql.executeQuery("SELECT count(*) FROM pg_temp.base_message")) { assertTrue(rows.next());assertEquals(1,rows.getInt(1)); }
        }
    }
 
}