Skip to content

Commit

Permalink
mv onetime logic to domain model, sync track in service
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefan committed Mar 16, 2024
1 parent 635c2f6 commit 246b002
Show file tree
Hide file tree
Showing 10 changed files with 61 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.github.binpastes.paste.api;

import com.github.binpastes.paste.api.model.CreateCmd;
import com.github.binpastes.paste.api.model.ListQuery;
import com.github.binpastes.paste.api.model.SearchQuery;
import com.github.binpastes.paste.api.model.SearchQuery.SearchItemView;
import com.github.binpastes.paste.api.model.DetailQuery;
import com.github.binpastes.paste.api.model.ListView;
import com.github.binpastes.paste.api.model.SearchView;
import com.github.binpastes.paste.api.model.SearchView.SearchItemView;
import com.github.binpastes.paste.api.model.DetailView;
import com.github.binpastes.paste.application.PasteService;
import com.github.binpastes.paste.domain.Paste;
import jakarta.validation.ConstraintViolationException;
Expand All @@ -28,7 +28,7 @@
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

import static com.github.binpastes.paste.api.model.ListQuery.ListItemQuery;
import static com.github.binpastes.paste.api.model.ListView.ListItemView;

@Validated
@RestController
Expand All @@ -45,7 +45,12 @@ public PasteController(final PasteService pasteService) {
}

@GetMapping("/{pasteId:[a-zA-Z0-9]{40}}")
public Mono<DetailQuery> findPaste(@PathVariable("pasteId") String pasteId, ServerHttpRequest request, ServerHttpResponse response) {
public Mono<DetailView> findPaste(
@PathVariable("pasteId")
String pasteId,
ServerHttpRequest request,
ServerHttpResponse response
) {
return pasteService
.find(pasteId)
.doOnNext(paste -> {
Expand All @@ -63,21 +68,21 @@ public Mono<DetailQuery> findPaste(@PathVariable("pasteId") String pasteId, Serv
CacheControl.maxAge(Duration.between(now, paste.getDateOfExpiry())));
}
})
.map(reference -> DetailQuery.of(reference, remoteAddress(request)))
.map(reference -> DetailView.of(reference, remoteAddress(request)))
.switchIfEmpty(Mono.error(new ResponseStatusException(HttpStatus.NOT_FOUND)));
}

@GetMapping
public Mono<ListQuery> findPastes() {
public Mono<ListView> findPastes() {
return pasteService
.findAll()
.map(ListItemQuery::of)
.map(ListItemView::of)
.collectList()
.map(ListQuery::of);
.map(ListView::of);
}

@GetMapping("/search")
public Mono<SearchQuery> searchPastes(
public Mono<SearchView> searchPastes(
@RequestParam("term")
@NotBlank
@Pattern(regexp = "[\\pL\\pN\\p{P}\\s]{3,25}")
Expand All @@ -89,12 +94,12 @@ public Mono<SearchQuery> searchPastes(
.findByFullText(term)
.map(paste -> SearchItemView.of(paste, term))
.collectList()
.map(SearchQuery::of);
.map(SearchView::of);
}

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public Mono<DetailQuery> createPaste(@Valid @RequestBody Mono<CreateCmd> createCmd, ServerHttpRequest request) {
public Mono<DetailView> createPaste(@Valid @RequestBody Mono<CreateCmd> createCmd, ServerHttpRequest request) {
return createCmd
.flatMap(cmd -> pasteService.create(
cmd.title(),
Expand All @@ -104,7 +109,7 @@ public Mono<DetailQuery> createPaste(@Valid @RequestBody Mono<CreateCmd> createC
cmd.pasteExposure(),
remoteAddress(request)
))
.map((Paste reference) -> DetailQuery.of(reference, remoteAddress(request)));
.map((Paste reference) -> DetailView.of(reference, remoteAddress(request)));
}

@DeleteMapping("/{pasteId:[a-zA-Z0-9]{40}}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import java.time.LocalDateTime;

public record DetailQuery(
public record DetailView(
String id,
String title,
String content,
Expand All @@ -18,8 +18,8 @@ public record DetailQuery(
LocalDateTime lastViewed,
long views
) {
public static DetailQuery of(final Paste reference, final String remoteAddress) {
return new DetailQuery(
public static DetailView of(final Paste reference, final String remoteAddress) {
return new DetailView(
reference.getId(),
reference.getTitle(),
reference.getContent(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@
import java.time.LocalDateTime;
import java.util.List;

public record ListQuery(
List<ListItemQuery> pastes
public record ListView(
List<ListItemView> pastes
) {
public static ListQuery of(final List<ListItemQuery> pastes) {
return new ListQuery(pastes);
public static ListView of(final List<ListItemView> pastes) {
return new ListView(pastes);
}

public record ListItemQuery(
public record ListItemView(
String id,
String title,
int sizeInBytes,
boolean isEncrypted,
LocalDateTime dateCreated,
LocalDateTime dateOfExpiry
) {
public static ListItemQuery of(final Paste reference) {
return new ListItemQuery(
public static ListItemView of(final Paste reference) {
return new ListItemView(
reference.getId(),
reference.getTitle(),
reference.getContent().getBytes().length,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
import java.time.LocalDateTime;
import java.util.List;

public record SearchQuery(
public record SearchView(
List<SearchItemView> pastes
) {

public static SearchQuery of(List<SearchItemView> pastes) {
return new SearchQuery(pastes);
public static SearchView of(List<SearchItemView> pastes) {
return new SearchView(pastes);
}

public record SearchItemView(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,17 @@ public Mono<Paste> find(String id) {
}

private Mono<Paste> trackAccess(Paste paste) {
trackingService.trackView(paste.getId());
var result = Mono.just(paste);

if (paste.isOneTime()) {
return pasteRepository
.save(paste.markAsExpired())
.retryWhen(Retry.indefinitely()
.filter(ex -> ex instanceof OptimisticLockingFailureException))
.doOnSuccess(deletedPaste -> log.info("OneTime paste {} viewed and burnt", deletedPaste.getId()));
return result
.map(p -> p.trackView(LocalDateTime.now()))
.flatMap(pasteRepository::save)
.doOnSuccess(burntPaste -> log.info("OneTime paste {} viewed and burnt", burntPaste.getId()));
}

return Mono.just(paste);
trackingService.trackView(paste.getId());
return result;
}

public Flux<Paste> findAll() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,13 @@ public Paste trackView(LocalDateTime lastViewed) {
setLastViewed(lastViewed);
}

return setViews(this.getViews() + 1);
setViews(getViews() + 1);

if (isOneTime()) {
markAsExpired();
}

return this;
}

public Paste markAsExpired() {
Expand All @@ -152,7 +158,7 @@ public Paste markAsExpired() {
return setDateOfExpiry(now);
}

throw new IllegalStateException("Paste is already expired");
throw new IllegalStateException("Paste has already expired: " + dateOfExpiry);
}

protected Paste setId(final String id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import com.tngtech.archunit.core.importer.ClassFileImporter;
import com.tngtech.archunit.core.importer.ImportOption;
import org.junit.jupiter.api.Test;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.RestController;

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noMethods;
Expand All @@ -24,7 +26,9 @@ void domainClassNeverRendered() {
var rule = noMethods()
.that()
.areDeclaredInClassesThat()
.resideInAPackage("com.github.binpastes.paste.api")
.areAnnotatedWith(RestController.class)
.or()
.areAnnotatedWith(Controller.class)
.should()
.haveRawReturnType(Paste.class);

Expand All @@ -41,9 +45,12 @@ void injectionsMindArchitecturalBorders() {

var rule = noClasses()
.that()
.resideInAPackage("com.github.binpastes.paste.api")
.areAnnotatedWith(RestController.class)
.or()
.areAnnotatedWith(Controller.class)
.should()
.dependOnClassesThat().areAnnotatedWith(Repository.class);
.dependOnClassesThat()
.areAnnotatedWith(Repository.class);

rule.check(importedClasses);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ void deleteOneTimePaste() {
}

private Paste givenOneTimePaste() {
return givenPaste(
return persistedPaste(
Paste.newInstance(
"someTitle",
"Lorem ipsum dolor sit amet",
Expand All @@ -167,7 +167,7 @@ private Paste givenOneTimePaste() {
);
}

private Paste givenPaste(Paste paste) {
private Paste persistedPaste(Paste paste) {
return pasteRepository.save(paste).block();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ void trackPaste() {
}

@Test
@DisplayName("tracking - concurrent tracking events result in exact result")
@DisplayName("tracking - concurrent tracking events result in exact view count")
void trackConcurrentPasteViews() {
var intialPaste = givenPublicPaste();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.github.binpastes.paste.api.model;

import com.github.binpastes.paste.api.model.SearchQuery.SearchItemView;
import com.github.binpastes.paste.api.model.SearchView.SearchItemView;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
Expand Down

0 comments on commit 246b002

Please sign in to comment.