Open-sourced generic, dynamic POC, RESTful alerting API

This commit is contained in:
2024-02-16 17:37:37 -07:00
parent b2ed41c549
commit 0d1d154c7a
70 changed files with 3272 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
import org.springframework.boot.gradle.tasks.bundling.BootJar
plugins {
id("org.flywaydb.flyway") version "7.9.1"
kotlin("plugin.jpa") version "1.5.10"
}
dependencies {
"implementation"("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-validation")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.flywaydb:flyway-core")
implementation("org.apache.tomcat:tomcat-jdbc")
implementation("com.h2database:h2:1.4.200")
}
flyway {
url = "jdbc:h2:mem:alerting"
user = "defaultUser"
password = "secret"
locations = arrayOf("classpath:resources/db/migration")
}
tasks.getByName<BootJar>("bootJar") {
enabled = true
mainClass.set("com.poc.alerting.persistence.Persistence")
}
@@ -0,0 +1,23 @@
package com.poc.alerting.persistence
import org.h2.tools.Server
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Profile
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
@Configuration
@EnableJpaRepositories("com.poc.alerting.persistence.repositories")
@EntityScan("com.poc.alerting.persistence.dto")
@EnableAutoConfiguration
open class H2Config {
@Bean(initMethod = "start", destroyMethod = "stop")
@Profile("persistence")
open fun inMemoryH2DatabaseServer(): Server {
return Server.createTcpServer(
"-tcp", "-tcpAllowOthers", "-tcpPort", "9091"
)
}
}
@@ -0,0 +1,12 @@
package com.poc.alerting.persistence
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication(scanBasePackages = ["com.poc.alerting.persistence"])
open class Persistence
fun main(args: Array<String>) {
runApplication<Persistence>(*args)
}
@@ -0,0 +1,22 @@
package com.poc.alerting.persistence.dto
import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.validation.constraints.NotBlank
import javax.validation.constraints.Size
@Entity
data class Account(
@Id
@GeneratedValue
val id: Long,
@NotBlank
@Size(max = 255)
val name: String,
@NotBlank
@Size(max = 255)
val extId: String
)
@@ -0,0 +1,65 @@
package com.poc.alerting.persistence.dto
import org.hibernate.annotations.CreationTimestamp
import org.hibernate.annotations.UpdateTimestamp
import java.util.Date
import javax.persistence.Entity
import javax.persistence.EnumType
import javax.persistence.Enumerated
import javax.persistence.GeneratedValue
import javax.persistence.GenerationType
import javax.persistence.Id
import javax.persistence.ManyToOne
import javax.persistence.Temporal
import javax.persistence.TemporalType
import javax.validation.constraints.NotBlank
import javax.validation.constraints.NotNull
import javax.validation.constraints.Size
@Entity
data class Alert(
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
val id: Long,
@NotBlank
@Size(max = 255)
val extId: String,
@Size(max = 255)
var threshold: String,
@NotNull
@Enumerated(EnumType.STRING)
val type: AlertTypeEnum,
@Size(max = 255)
var frequency: String = "",
var enabled: String = "",
@Temporal(TemporalType.TIMESTAMP)
var lastTriggerTimestamp: Date,
@Temporal(TemporalType.TIMESTAMP)
var notificationSentTimestamp: Date,
var isTriggered: Boolean,
@Size(max = 255)
var referenceTimePeriod: String,
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
val created: Date,
@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
var updated: Date,
@Size(max = 255)
var updatedBy: String,
@ManyToOne
var account: Account
)
@@ -0,0 +1,8 @@
package com.poc.alerting.persistence.dto
import kotlin.random.Random
enum class AlertTypeEnum(val query: () -> Int) {
HARDCODED_ALERT_1({ Random.nextInt(0,1000) }),
HARDCODED_ALERT_2({ Random.nextInt(0,1000) })
}
@@ -0,0 +1,58 @@
package com.poc.alerting.persistence.dto
import org.hibernate.annotations.CreationTimestamp
import org.hibernate.annotations.UpdateTimestamp
import java.util.Date
import javax.persistence.Entity
import javax.persistence.EnumType
import javax.persistence.Enumerated
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.ManyToOne
import javax.persistence.Temporal
import javax.persistence.TemporalType
import javax.validation.constraints.NotBlank
import javax.validation.constraints.NotNull
import javax.validation.constraints.Size
@Entity
data class Recipient(
@Id
@GeneratedValue
val id: Long,
@NotBlank
@Size(max = 255)
val extId: String,
@NotBlank
@Size(max = 255)
val recipient: String,
@NotNull
@Enumerated(EnumType.STRING)
val type: RecipientTypeEnum,
@Size(max = 255)
val username: String,
@Size(max = 255)
val password: String,
@CreationTimestamp
@Temporal(TemporalType.TIMESTAMP)
val created: Date,
@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
val updated: Date,
@Size(max = 255)
val updatedBy: String,
@ManyToOne
val alert: Alert,
@ManyToOne
val account: Account
)
@@ -0,0 +1,7 @@
package com.poc.alerting.persistence.dto
enum class RecipientTypeEnum {
EMAIL,
SMS,
HTTP
}
@@ -0,0 +1,10 @@
package com.poc.alerting.persistence.repositories
import com.poc.alerting.persistence.dto.Account
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.stereotype.Repository
@Repository
interface AccountRepository : JpaRepository<Account, Long> {
fun findByExtId(accountExtId: String): Account
}
@@ -0,0 +1,13 @@
package com.poc.alerting.persistence.repositories
import com.poc.alerting.persistence.dto.Alert
import org.springframework.data.repository.CrudRepository
import org.springframework.data.repository.PagingAndSortingRepository
import org.springframework.stereotype.Repository
@Repository
interface AlertRepository : CrudRepository<Alert, Long>, PagingAndSortingRepository<Alert, Long> {
fun findByExtIdAndAccount_ExtId(alertId: String, accountExtId: String): Alert
fun findAllByAccount_ExtId(accountExtId: String): List<Alert>
}
@@ -0,0 +1,14 @@
package com.poc.alerting.persistence.repositories
import com.poc.alerting.persistence.dto.Recipient
import org.springframework.data.repository.CrudRepository
import org.springframework.stereotype.Repository
@Repository
interface RecipientRepository : CrudRepository<Recipient, Long> {
fun findByExtIdAndAlert_ExtIdAndAccount_ExtId(recipientId: String, alertId: String, accountExtId: String): Recipient
fun findAllByAccount_ExtId(accountExtId: String): List<Recipient>
fun findAllByAlert_ExtIdAndAccount_ExtId(alertId: String, accountExtId: String): List<Recipient>
}
@@ -0,0 +1,21 @@
spring:
profiles:
active: "persistence"
datasource:
url: "jdbc:h2:mem:alerting;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE;"
driver-class-name: org.h2.Driver
username: defaultUser
password: secret
jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: update
naming:
implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy
physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
h2:
console:
enabled: true
path: /h2-console
server:
port: 8081
@@ -0,0 +1,11 @@
DROP TABLE qrtz_calendars IF EXISTS;
DROP TABLE qrtz_cron_triggers IF EXISTS;
DROP TABLE qrtz_fired_triggeres IF EXISTS;
DROP TABLE qrtz_paused_trigger_grps IF EXISTS;
DROP TABLE qrtz_scheduler_state IF EXISTS;
DROP TABLE qrtz_locks IF EXISTS;
DROP TABLE qrtz_job_details IF EXISTS;
DROP TABLE qrtz_simple_triggers IF EXISTS;
DROP TABLE qrtz_simprop_triggers IF EXISTS;
DROP TABLE qrtz_blob_triggers IF EXISTS;
DROP TABLE qrtz_triggers IF EXISTS;
@@ -0,0 +1,238 @@
CREATE TABLE QRTZ_CALENDARS (
SCHED_NAME VARCHAR(120) NOT NULL,
CALENDAR_NAME VARCHAR (200) NOT NULL ,
CALENDAR IMAGE NOT NULL
);
CREATE TABLE QRTZ_CRON_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR (200) NOT NULL ,
TRIGGER_GROUP VARCHAR (200) NOT NULL ,
CRON_EXPRESSION VARCHAR (120) NOT NULL ,
TIME_ZONE_ID VARCHAR (80)
);
CREATE TABLE QRTZ_FIRED_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
ENTRY_ID VARCHAR (95) NOT NULL ,
TRIGGER_NAME VARCHAR (200) NOT NULL ,
TRIGGER_GROUP VARCHAR (200) NOT NULL ,
INSTANCE_NAME VARCHAR (200) NOT NULL ,
FIRED_TIME BIGINT NOT NULL ,
SCHED_TIME BIGINT NOT NULL ,
PRIORITY INTEGER NOT NULL ,
STATE VARCHAR (16) NOT NULL,
JOB_NAME VARCHAR (200) NULL ,
JOB_GROUP VARCHAR (200) NULL ,
IS_NONCONCURRENT BOOLEAN NULL ,
REQUESTS_RECOVERY BOOLEAN NULL
);
CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_GROUP VARCHAR (200) NOT NULL
);
CREATE TABLE QRTZ_SCHEDULER_STATE (
SCHED_NAME VARCHAR(120) NOT NULL,
INSTANCE_NAME VARCHAR (200) NOT NULL ,
LAST_CHECKIN_TIME BIGINT NOT NULL ,
CHECKIN_INTERVAL BIGINT NOT NULL
);
CREATE TABLE QRTZ_LOCKS (
SCHED_NAME VARCHAR(120) NOT NULL,
LOCK_NAME VARCHAR (40) NOT NULL
);
CREATE TABLE QRTZ_JOB_DETAILS (
SCHED_NAME VARCHAR(120) NOT NULL,
JOB_NAME VARCHAR (200) NOT NULL ,
JOB_GROUP VARCHAR (200) NOT NULL ,
DESCRIPTION VARCHAR (250) NULL ,
JOB_CLASS_NAME VARCHAR (250) NOT NULL ,
IS_DURABLE BOOLEAN NOT NULL ,
IS_NONCONCURRENT BOOLEAN NOT NULL ,
IS_UPDATE_DATA BOOLEAN NOT NULL ,
REQUESTS_RECOVERY BOOLEAN NOT NULL ,
JOB_DATA IMAGE NULL
);
CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR (200) NOT NULL ,
TRIGGER_GROUP VARCHAR (200) NOT NULL ,
REPEAT_COUNT BIGINT NOT NULL ,
REPEAT_INTERVAL BIGINT NOT NULL ,
TIMES_TRIGGERED BIGINT NOT NULL
);
CREATE TABLE QRTZ_SIMPROP_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR(200) NOT NULL,
TRIGGER_GROUP VARCHAR(200) NOT NULL,
STR_PROP_1 VARCHAR(512) NULL,
STR_PROP_2 VARCHAR(512) NULL,
STR_PROP_3 VARCHAR(512) NULL,
INT_PROP_1 INTEGER NULL,
INT_PROP_2 INTEGER NULL,
LONG_PROP_1 BIGINT NULL,
LONG_PROP_2 BIGINT NULL,
DEC_PROP_1 NUMERIC(13,4) NULL,
DEC_PROP_2 NUMERIC(13,4) NULL,
BOOL_PROP_1 BOOLEAN NULL,
BOOL_PROP_2 BOOLEAN NULL
);
CREATE TABLE QRTZ_BLOB_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR (200) NOT NULL ,
TRIGGER_GROUP VARCHAR (200) NOT NULL ,
BLOB_DATA IMAGE NULL
);
CREATE TABLE QRTZ_TRIGGERS (
SCHED_NAME VARCHAR(120) NOT NULL,
TRIGGER_NAME VARCHAR (200) NOT NULL ,
TRIGGER_GROUP VARCHAR (200) NOT NULL ,
JOB_NAME VARCHAR (200) NOT NULL ,
JOB_GROUP VARCHAR (200) NOT NULL ,
DESCRIPTION VARCHAR (250) NULL ,
NEXT_FIRE_TIME BIGINT NULL ,
PREV_FIRE_TIME BIGINT NULL ,
PRIORITY INTEGER NULL ,
TRIGGER_STATE VARCHAR (16) NOT NULL ,
TRIGGER_TYPE VARCHAR (8) NOT NULL ,
START_TIME BIGINT NOT NULL ,
END_TIME BIGINT NULL ,
CALENDAR_NAME VARCHAR (200) NULL ,
MISFIRE_INSTR SMALLINT NULL ,
JOB_DATA IMAGE NULL
);
ALTER TABLE QRTZ_CALENDARS ADD
CONSTRAINT PK_QRTZ_CALENDARS PRIMARY KEY
(
SCHED_NAME,
CALENDAR_NAME
);
ALTER TABLE QRTZ_CRON_TRIGGERS ADD
CONSTRAINT PK_QRTZ_CRON_TRIGGERS PRIMARY KEY
(
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
);
ALTER TABLE QRTZ_FIRED_TRIGGERS ADD
CONSTRAINT PK_QRTZ_FIRED_TRIGGERS PRIMARY KEY
(
SCHED_NAME,
ENTRY_ID
);
ALTER TABLE QRTZ_PAUSED_TRIGGER_GRPS ADD
CONSTRAINT PK_QRTZ_PAUSED_TRIGGER_GRPS PRIMARY KEY
(
SCHED_NAME,
TRIGGER_GROUP
);
ALTER TABLE QRTZ_SCHEDULER_STATE ADD
CONSTRAINT PK_QRTZ_SCHEDULER_STATE PRIMARY KEY
(
SCHED_NAME,
INSTANCE_NAME
);
ALTER TABLE QRTZ_LOCKS ADD
CONSTRAINT PK_QRTZ_LOCKS PRIMARY KEY
(
SCHED_NAME,
LOCK_NAME
);
ALTER TABLE QRTZ_JOB_DETAILS ADD
CONSTRAINT PK_QRTZ_JOB_DETAILS PRIMARY KEY
(
SCHED_NAME,
JOB_NAME,
JOB_GROUP
);
ALTER TABLE QRTZ_SIMPLE_TRIGGERS ADD
CONSTRAINT PK_QRTZ_SIMPLE_TRIGGERS PRIMARY KEY
(
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
);
ALTER TABLE QRTZ_SIMPROP_TRIGGERS ADD
CONSTRAINT PK_QRTZ_SIMPROP_TRIGGERS PRIMARY KEY
(
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
);
ALTER TABLE QRTZ_TRIGGERS ADD
CONSTRAINT PK_QRTZ_TRIGGERS PRIMARY KEY
(
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
);
ALTER TABLE QRTZ_CRON_TRIGGERS ADD
CONSTRAINT FK_QRTZ_CRON_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
(
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
) REFERENCES QRTZ_TRIGGERS (
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
) ON DELETE CASCADE;
ALTER TABLE QRTZ_SIMPLE_TRIGGERS ADD
CONSTRAINT FK_QRTZ_SIMPLE_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
(
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
) REFERENCES QRTZ_TRIGGERS (
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
) ON DELETE CASCADE;
ALTER TABLE QRTZ_SIMPROP_TRIGGERS ADD
CONSTRAINT FK_QRTZ_SIMPROP_TRIGGERS_QRTZ_TRIGGERS FOREIGN KEY
(
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
) REFERENCES QRTZ_TRIGGERS (
SCHED_NAME,
TRIGGER_NAME,
TRIGGER_GROUP
) ON DELETE CASCADE;
ALTER TABLE QRTZ_TRIGGERS ADD
CONSTRAINT FK_QRTZ_TRIGGERS_QRTZ_JOB_DETAILS FOREIGN KEY
(
SCHED_NAME,
JOB_NAME,
JOB_GROUP
) REFERENCES QRTZ_JOB_DETAILS (
SCHED_NAME,
JOB_NAME,
JOB_GROUP
);
COMMIT;
@@ -0,0 +1,63 @@
CREATE TABLE `account` (
`id` long PRIMARY KEY,
`name` varchar(255) NOT NULL,
`ext_id` varchar(255) NOT NULL
);
INSERT INTO `account`
VALUES (1, 'Test Account 1', '1111'),
(2, 'Test Account 2', '2222');
CREATE TABLE `alert` (
`id` long PRIMARY KEY AUTO_INCREMENT,
`ext_id` varchar(255) UNIQUE NOT NULL,
`name` varchar(255),
`threshold` varchar(255),
`type` ENUM ('HARDCODED_ALERT_1', 'HARDCODED_ALERT_2'),
`frequency` varchar(255),
`enabled` boolean default false,
`last_trigger_timestamp` timestamp,
`notification_sent_timestamp` timestamp,
`is_triggered` boolean default false,
`reference_time_period` varchar(255),
`created` timestamp,
`updated` timestamp,
`updated_by` varchar(255),
`account_id` long NOT NULL
);
INSERT INTO `alert`
VALUES (1, '1111-alert-1', 'Some Test Alert for Account 1111', '90', 'HARDCODED_ALERT_1', '15m', true, '2021-04-22 16:33:21.959', '2021-04-22 16:33:21.959', false, '1 Month', '2021-04-22 16:33:21.959', '2021-04-22 16:33:21.959', 'someUser1', 1),
(2, '1111-alert-2', 'Some Other Test Alert for Account 1111', '666', 'HARDCODED_ALERT_2', '5m', true, null, null, false, '1 Week', '2021-04-22 16:33:21.959', '2021-04-26 04:01:13.448', 'someUser1', 1),
(3, '2222-alert-1', 'Some Test Alert for Account 2222', '90', 'HARDCODED_ALERT_1', '15m', true, '2021-04-22 16:33:21.959', '2021-04-22 16:33:21.959', false, '1 Month', '2021-04-22 16:33:21.959', '2021-04-22 16:33:21.959', 'someOtherUser2', 2),
(4, '2222-alert-2', 'Some Other Test Alert for Account 2222', '666', 'HARDCODED_ALERT_2', '5m', true, null, null, false, '1 Week', '2021-04-22 16:33:21.959', '2021-04-26 04:01:13.448', 'someOtherUser2', 2);
ALTER TABLE `alert` ADD FOREIGN KEY (`account_id`) REFERENCES `account` (`id`);
CREATE TABLE `recipient` (
`id` long PRIMARY KEY AUTO_INCREMENT,
`ext_id` varchar(255) UNIQUE NOT NULL,
`recipient` varchar(255) NOT NULL,
`type` ENUM ('EMAIL', 'SMS', 'HTTP'),
`username` varchar(255),
`password` varchar(255),
`created` timestamp NOT NULL,
`updated` timestamp NOT NULL,
`updated_by` varchar(255) NOT NULL,
`alert_id` long,
`account_id` long
);
INSERT INTO `recipient`
VALUES (1, 'someUsersEmail-account-1111', 'someUser1@somedomain.com', 'EMAIL', null, null, '2021-02-22 16:09:28.139', '2021-02-22 16:09:28.139', 'someUser1', 1, 1),
(2, 'someOtherUsersEmail-account-1111', 'someOtherUser1@somedomain.com', 'EMAIL', null, null, '2021-03-04 07:17:33.244', '2021-03-04 08:00:54.562', 'someOtherUser1', 1, 1),
(3, 'someUserHttpRecipient-account-1111', 'https://some.test.callback.com/callback1', 'HTTP', 'mikeRoweSoft', 'iSuPpOrTwInDoWs', '2021-05-19 02:39:12.922', '2021-05-19 02:39:12.922', 'someUser1', 2, 1),
(4, 'someUserHttpRecipient-account-2222', 'https://some.test.callback.com/callback2', 'HTTP', 'teriDactyl', 'L1f3F1nd$AWay', '2021-05-19 02:39:12.922', '2021-05-19 02:39:12.922', 'someUser2', 2, 2),
(5, 'someUsersEmail-account-2222', 'someUser2@somedomain.com', 'EMAIL', null, null, '2021-02-22 16:09:28.139', '2021-02-22 16:09:28.139', 'someUser2', 1, 2),
(6, 'someOtherUsersSms-account-2222', '13035552222', 'SMS', null, null, '2021-02-22 16:09:28.139', '2021-02-22 16:09:28.139', 'someOtherUser2', 1, 2);
ALTER TABLE `recipient` ADD FOREIGN KEY (`alert_id`) REFERENCES `alert` (`id`);
ALTER TABLE `recipient` ADD FOREIGN KEY (`account_id`) REFERENCES `account` (`id`);
CREATE SEQUENCE `hibernate_sequence` START WITH 5 INCREMENT BY 1;