Skip to content

Commit

Permalink
Added priority, fixed json issues, etc (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
farjamm committed Dec 23, 2024
1 parent 3103b8e commit a609718
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import no.nav.data.common.rest.RestResponsePage;
import no.nav.data.common.security.SecurityUtils;
import no.nav.data.etterlevelse.krav.domain.Tilbakemelding;
import no.nav.data.etterlevelse.krav.domain.TilbakemeldingStatus;
import no.nav.data.etterlevelse.krav.dto.CreateTilbakemeldingRequest;
import no.nav.data.etterlevelse.krav.dto.EditTilbakemeldingRequest;
import no.nav.data.etterlevelse.krav.dto.TilbakemeldingNewMeldingRequest;
import no.nav.data.etterlevelse.krav.dto.TilbakemeldingResponse;
import no.nav.data.integration.slack.SlackService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
Expand All @@ -33,6 +35,7 @@ public class TilbakemeldingController {

private final TilbakemeldingService tilbakemeldingService;
private final TilbakemeldingValidator validator;
private final SlackService slackService;

// Tilbakemelding

Expand Down Expand Up @@ -99,6 +102,17 @@ public ResponseEntity<TilbakemeldingResponse> updateTilbakemeldingStatusAndEndre
var tilbakemelding = tilbakemeldingService.updateTilbakemeldingStatusAndEndretKrav(tilbakeMeldingId, status, endretkrav);
return ResponseEntity.ok(tilbakemelding.toResponse());
}

@Operation(summary = "Initiates sending of all pending slack messages (admin use only)")
@ApiResponse(description = "Pending slack messages sent")
@GetMapping("/flushSlack")
public void flushSlack() {
if (!SecurityUtils.isAdmin()) {
log.info("Ignoring request to flush slack messages: user not admin");
}
log.info("Requested to flush pending slack messages");
slackService.sendAll();
}

static class TilbakemeldingPage extends RestResponsePage<TilbakemeldingResponse> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import no.nav.data.common.security.SecurityProperties;
import no.nav.data.etterlevelse.varsel.domain.Varsel;
import no.nav.data.etterlevelse.varsel.domain.Varslingsadresse;
import no.nav.data.integration.slack.SlackMelding;
import no.nav.data.integration.slack.SlackService;
import org.apache.commons.lang3.NotImplementedException;
import org.springframework.stereotype.Service;
Expand All @@ -24,17 +25,18 @@ public void varsle(List<Varslingsadresse> recipients, Varsel varsel) {
for (Varslingsadresse varslingsadresse : recipients) {
switch (varslingsadresse.getType()) {
case EPOST -> emailService.scheduleMail(MailTask.builder().to(varslingsadresse.getAdresse()).subject(varsel.getTitle()).body(varsel.toHtml()).build());
case SLACK -> slackService.sendMessageToChannel(varslingsadresse.getAdresse(), varsel.toSlack());
case SLACK -> slackService.sendMessageToChannel(varslingsadresse.getAdresse(), varsel.toSlack(), SlackMelding.PRIORITY_LOW);
case SLACK_USER -> {
if (securityProperties.isDev()) {
slackService.sendMessageToChannel(varslingsadresse.getAdresse(), varsel.toSlack());
slackService.sendMessageToChannel(varslingsadresse.getAdresse(), varsel.toSlack(), SlackMelding.PRIORITY_LOW);
} else {
slackService.sendMessageToUser(varslingsadresse.getAdresse(), varsel.toSlack());
slackService.sendMessageToUser(varslingsadresse.getAdresse(), varsel.toSlack(), SlackMelding.PRIORITY_LOW);
}
}
default -> throw new NotImplementedException("%s is not an implemented varsel type".formatted(varslingsadresse.getType()));
}
};

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import lombok.NoArgsConstructor;
import lombok.Singular;
import lombok.Value;
import no.nav.data.integration.slack.dto.SlackDtos.PostMessageRequest.Block;
import no.nav.data.integration.slack.dto.SlackDtos.Block;

import java.util.ArrayList;
import java.util.Arrays;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
import no.nav.data.common.web.TraceHeaderRequestInterceptor;
import no.nav.data.etterlevelse.varsel.domain.SlackChannel;
import no.nav.data.etterlevelse.varsel.domain.SlackUser;
import no.nav.data.integration.slack.dto.SlackDtos.Block;
import no.nav.data.integration.slack.dto.SlackDtos.Channel;
import no.nav.data.integration.slack.dto.SlackDtos.CreateConversationRequest;
import no.nav.data.integration.slack.dto.SlackDtos.CreateConversationResponse;
import no.nav.data.integration.slack.dto.SlackDtos.ListChannelResponse;
import no.nav.data.integration.slack.dto.SlackDtos.PostMessageRequest;
import no.nav.data.integration.slack.dto.SlackDtos.PostMessageRequest.Block;
import no.nav.data.integration.slack.dto.SlackDtos.PostMessageResponse;
import no.nav.data.integration.slack.dto.SlackDtos.Response;
import no.nav.data.integration.slack.dto.SlackDtos.UserResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import no.nav.data.integration.slack.dto.SlackDtos.PostMessageRequest.Block;
import no.nav.data.integration.slack.dto.SlackDtos.Block;
import org.hibernate.annotations.Type;

import java.util.List;
Expand All @@ -30,6 +29,9 @@
@Entity
@Table(name = "SLACK_MELDING")
public class SlackMelding {

public static final int PRIORITY_LOW = 0;
public static final int PRIORITY_HIGH = 10;

@Id
@SequenceGenerator(name = "slack_melding_id_seq", sequenceName = "slack_melding_id_seq", allocationSize = 1)
Expand All @@ -42,9 +44,11 @@ public class SlackMelding {
@Builder.Default
private SlackMeldingData data = new SlackMeldingData();

public SlackMelding(String mottager, boolean tilKanal, List<Block> blocks) {
public SlackMelding(String mottager, boolean tilKanal, int prioritet, List<Block> blocks) {
data = new SlackMeldingData();
data.mottager = mottager;
data.sendTilKanal = tilKanal;
data.prioritet = prioritet;
data.blocks = blocks;
}

Expand All @@ -53,8 +57,18 @@ public SlackMelding(String mottager, boolean tilKanal, List<Block> blocks) {
@NoArgsConstructor
@AllArgsConstructor
public static class SlackMeldingData {

/*
* OBS!!! Instanser av denne klassen vil bli serialisert til en arbeidstabell, og der kan de være i flere dager. Derfor:
* Ikke gjør endringer her som medfører at eksisterende rader i arbeidstabellen ikke lar seg deserialisere!
* Ikke gjør endringer her som medfører at eksisterende rader i arbeidstabellen ikke lar seg deserialisere!
* Ikke gjør endringer her som medfører at eksisterende rader i arbeidstabellen ikke lar seg deserialisere!
* Se no.nav.data.etterlevelse.krav.TilbakemeldingController.flushSlack() for manuell tømmin av arbeidstabellen.
*/

private String mottager;
private boolean sendTilKanal;
private int prioritet; // == 0 → send bulk, >= 10 → send ASAP
private List<Block> blocks;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

import java.util.Optional;

public interface SlackMeldingRepo extends JpaRepository<SlackMelding, Integer> {

@Query(value = "select * from slack_melding limit 1", nativeQuery = true)
public SlackMelding getOne();
@Query(value = "select * from slack_melding where data ->> prioritet >= ?1 limit 1", nativeQuery = true)
public Optional<SlackMelding> getOneWithPriority(int priorityThreshold);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import no.nav.data.integration.slack.dto.SlackDtos.PostMessageRequest.Block;
import no.nav.data.integration.slack.dto.SlackDtos.Block;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
Expand All @@ -20,38 +20,50 @@ public class SlackService {
private final SlackClient slackClient;

@Transactional(propagation = Propagation.REQUIRED)
public void sendMessageToChannel(String mottager, List<Block> blocks) {
SlackMelding sm = new SlackMelding(mottager, false, blocks);
public void sendMessageToChannel(String mottager, List<Block> blocks, int priority) {
SlackMelding sm = new SlackMelding(mottager, false, priority, blocks);
repo.save(sm);
}

@Transactional(propagation = Propagation.REQUIRED)
public void sendMessageToUser(String mottager, List<Block> blocks) {
SlackMelding sm = new SlackMelding(mottager, true, blocks);
public void sendMessageToUser(String mottager, List<Block> blocks, int priority) {
SlackMelding sm = new SlackMelding(mottager, true, priority, blocks);
repo.save(sm);
}

@SchedulerLock(name = "sendSlack")
@Scheduled(cron = "0 0 13 * * *") // Happens every day at 1300
@SchedulerLock(name = "sendSlackEnGros")
@Scheduled(cron = "0 55 12 * * *") // Happens every day at 12:55:00
public void sendAll() {
log.info("Sending all pending slack messages...");
int sendCount = 0;
while (repo.count() > 0) {
sendOneMessage();
while (sendOneMessage(SlackMelding.PRIORITY_LOW)) {
sendCount++;
}
log.info("Done sending {} pending slack messages", sendCount);
}

@SchedulerLock(name = "sendSlackPriority")
@Scheduled(cron = "10 * * * * *") // Happens every minute at 10 seconds.
public void sendHighPriority() {
int sendCount = 0;
while (sendOneMessage(SlackMelding.PRIORITY_HIGH)) {
sendCount++;
}
log.info("Done sending {} high priority slack messages", sendCount);
}

@Transactional()
private void sendOneMessage() {
SlackMelding sm = repo.getOne();
// Returns true if there was a pending message to send, false otherwise.
private boolean sendOneMessage(int priority) {
SlackMelding sm = repo.getOneWithPriority(priority).orElse(null);
if (sm == null) return false;
if (sm.getSendTilKanal()) {
slackClient.sendMessageToChannel(sm.getMottager(), sm.getBlocks());
} else {
slackClient.sendMessageToUserId(sm.getMottager(), sm.getBlocks());
}
repo.delete(sm);
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.Value;
import no.nav.data.common.utils.JsonUtils;
import no.nav.data.etterlevelse.varsel.domain.SlackChannel;
Expand All @@ -13,62 +15,79 @@

import java.util.List;

public class SlackDtos {
public final class SlackDtos {

// FIXME

/*
* OBS!!! Instanser av noen av klassen her (Block m/ innhold) vil bli serialisert til en arbeidstabell, og der kan
* de være i flere dager. Derfor:
* Ikke gjør endringer her som medfører at eksisterende rader i arbeidstabellen ikke lar seg deserialisere!
* Ikke gjør endringer her som medfører at eksisterende rader i arbeidstabellen ikke lar seg deserialisere!
* Ikke gjør endringer her som medfører at eksisterende rader i arbeidstabellen ikke lar seg deserialisere!
* Se no.nav.data.etterlevelse.krav.TilbakemeldingController.flushSlack() for manuell tømmin av arbeidstabellen.
*/

@Value
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class PostMessageRequest {
private String channel = null;
private List<Block> blocks = null;
}

String channel;
List<Block> blocks;

@Value
public static class Block {

public static Block header(String text) {
return new Block(BlockType.header, Text.plain(text));
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Block {

public static Block text(String text) {
return new Block(BlockType.section, Text.markdown(text));
}
private BlockType type = null;
@JsonInclude(Include.NON_NULL)
private Text text = null;

public static Block divider() {
return new Block(BlockType.divider, null);
}
public static Block header(String text) {
return new Block(BlockType.header, Text.plain(text));
}

/**
* Create Block with text, keeping other properties
*/
public Block withText(String newText) {
Assert.isTrue(text != null, "this is not a text block");
return new Block(type, new Text(text.type, newText));
}
public static Block text(String text) {
return new Block(BlockType.section, Text.markdown(text));
}

public enum BlockType {
header, section, divider
}
public static Block divider() {
return new Block(BlockType.divider, null);
}

BlockType type;
@JsonInclude(Include.NON_NULL)
Text text;
/**
* Create Block with text, keeping other properties
*/
public Block withText(String newText) {
Assert.isTrue(text != null, "this is not a text block");
return new Block(type, new Text(text.type, newText));
}
}

@Value
public static class Text {
public enum BlockType {
header, section, divider
}

enum TextType {mrkdwn, plain_text}
public enum TextType {
mrkdwn, plain_text
}

TextType type;
String text;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Text {

public static Text plain(String text) {
return new Text(TextType.plain_text, text);
}
private TextType type;
private String text;

public static Text markdown(String text) {
return new Text(TextType.mrkdwn, text);
public static Text plain(String text) {
return new Text(TextType.plain_text, text);
}

}
}
public static Text markdown(String text) {
return new Text(TextType.mrkdwn, text);
}
}

Expand Down

0 comments on commit a609718

Please sign in to comment.