Skip to content

Commit

Permalink
Added purging deleted comics from the library [comixed#1072]
Browse files Browse the repository at this point in the history
 * Added a frontend feature to initial the process.
 * Added a REST API to process the request.
 * Added a batch process to perform the purging.
 * Added state events to perform the record deletions.
  • Loading branch information
mcpierce committed Nov 5, 2021
1 parent 75505d9 commit 6fa7bcc
Show file tree
Hide file tree
Showing 56 changed files with 1,712 additions and 105 deletions.
@@ -0,0 +1,93 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

package org.comixedproject.batch.comicbooks;

import lombok.extern.log4j.Log4j2;
import org.comixedproject.batch.comicbooks.processors.PurgeMarkedComicsProcessor;
import org.comixedproject.batch.comicbooks.readers.PurgeMarkedComicsReader;
import org.comixedproject.batch.comicbooks.writers.PurgeMarkedComicsWriter;
import org.comixedproject.model.comicbooks.Comic;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* <code>PurgeLibraryConfiguration</code> defines a batch process that deletes comics that have been
* marked for purging.
*
* @author Darryl L. Pierce
*/
@Configuration
@Log4j2
public class PurgeLibraryConfiguration {
public static final String JOB_PURGE_LIBRARY_START = "job.purge-library.started";

@Value("${batch.chunk-size}")
private int batchChunkSize = 10;

/**
* Returns the purge library job.
*
* @param jobBuilderFactory the job factory
* @param purgeMarkedComicsStep the purge library step
* @return the job
*/
@Bean
@Qualifier("purgeLibraryJob")
public Job purgeLibraryJob(
final JobBuilderFactory jobBuilderFactory,
@Qualifier("purgeMarkedComicsStep") final Step purgeMarkedComicsStep) {
return jobBuilderFactory
.get("purgeLibraryJob")
.incrementer(new RunIdIncrementer())
.start(purgeMarkedComicsStep)
.build();
}

/**
* Returns the purge marked comics step.
*
* @param stepBuilderFactory the step factory
* @param reader the reader
* @param processor the processor
* @param writer the writer
* @return the step
*/
@Bean
@Qualifier("purgeMarkedComicsStep")
public Step purgeMarkedComicsStep(
final StepBuilderFactory stepBuilderFactory,
final PurgeMarkedComicsReader reader,
final PurgeMarkedComicsProcessor processor,
final PurgeMarkedComicsWriter writer) {
return stepBuilderFactory
.get("purgeMarkedComicsStep")
.<Comic, Comic>chunk(this.batchChunkSize)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
}
@@ -0,0 +1,44 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

package org.comixedproject.batch.comicbooks.processors;

import lombok.extern.log4j.Log4j2;
import org.comixedproject.model.comicbooks.Comic;
import org.comixedproject.service.comicbooks.ComicService;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* <code>PurgeMarkedComicsProcessor</code> deletes the comic that was marked for purging.
*
* @author Darryl L. Pierce
*/
@Component
@Log4j2
public class PurgeMarkedComicsProcessor implements ItemProcessor<Comic, Comic> {
@Autowired private ComicService comicService;

@Override
public Comic process(final Comic comic) throws Exception {
log.debug("Purging comic: id={}", comic.getId());
this.comicService.deleteComic(comic);
return comic;
}
}
@@ -0,0 +1,43 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

package org.comixedproject.batch.comicbooks.readers;

import java.util.List;
import lombok.extern.log4j.Log4j2;
import org.comixedproject.model.comicbooks.Comic;
import org.comixedproject.service.comicbooks.ComicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
* <code>PurgeMarkedComicsReader</code> provides a reader that loads comics marked for purging.
*
* @author Darryl L. Pierce
*/
@Component
@Log4j2
public class PurgeMarkedComicsReader extends AbstractComicReader {
@Autowired private ComicService comicService;

@Override
protected List<Comic> doLoadComics() {
log.trace("Loading comics marked for purging");
return this.comicService.findComicsMarkedForPurging();
}
}
@@ -0,0 +1,36 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

package org.comixedproject.batch.comicbooks.writers;

import lombok.extern.log4j.Log4j2;
import org.comixedproject.state.comicbooks.ComicEvent;
import org.springframework.stereotype.Component;

/**
* <code>PurgeMarkedComicsWriter</code> fires an event after a comic has been purged.
*
* @author Darryl L. Pierce
*/
@Component
@Log4j2
public class PurgeMarkedComicsWriter extends AbstractComicWriter {
public PurgeMarkedComicsWriter() {
super(ComicEvent.comicPurged);
}
}
@@ -0,0 +1,55 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

package org.comixedproject.batch.comicbooks.processors;

import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertSame;

import java.util.ArrayList;
import java.util.List;
import org.comixedproject.model.comicbooks.Comic;
import org.comixedproject.model.comicpages.Page;
import org.comixedproject.service.comicbooks.ComicService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class PurgeMarkedComicsProcessorTest {
@InjectMocks private PurgeMarkedComicsProcessor processor;
@Mock private ComicService comicService;
@Mock private Comic comic;

private List<Page> pageList = new ArrayList<>();

@Test
public void testProcess() throws Exception {
Mockito.doNothing().when(comicService).deleteComic(Mockito.any(Comic.class));

final Comic result = processor.process(comic);

assertNotNull(result);
assertSame(comic, result);

Mockito.verify(comicService, Mockito.times(1)).deleteComic(comic);
}
}
@@ -0,0 +1,83 @@
/*
* ComiXed - A digital comic book library management application.
* Copyright (C) 2021, The ComiXed Project
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses>
*/

package org.comixedproject.batch.comicbooks.readers;

import static junit.framework.TestCase.*;

import java.util.ArrayList;
import java.util.List;
import org.comixedproject.model.comicbooks.Comic;
import org.comixedproject.service.comicbooks.ComicService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class PurgeMarkedComicsReaderTest {
private static final int MAX_RECORDS = 25;

@InjectMocks private PurgeMarkedComicsReader reader;
@Mock private ComicService comicService;
@Mock private Comic comic;

private final List<Comic> comicList = new ArrayList<>();

@Test
public void testReadNoneLoadedManyFound() {
for (int index = 0; index < MAX_RECORDS; index++) comicList.add(comic);

Mockito.when(comicService.findComicsMarkedForPurging()).thenReturn(comicList);

final Comic result = reader.read();

assertNotNull(result);
assertSame(comic, result);
assertFalse(comicList.isEmpty());
assertEquals(MAX_RECORDS - 1, comicList.size());

Mockito.verify(comicService, Mockito.times(1)).findComicsMarkedForPurging();
}

@Test
public void testReadNoneRemaining() {
reader.comicList = comicList;

final Comic result = reader.read();

assertNull(result);
assertNull(reader.comicList);

Mockito.verify(comicService, Mockito.never()).findComicsMarkedForPurging();
}

@Test
public void testReadNoneLoadedNoneFound() {
Mockito.when(comicService.findComicsMarkedForPurging()).thenReturn(comicList);

final Comic result = reader.read();

assertNull(result);
assertNull(reader.comicList);

Mockito.verify(comicService, Mockito.times(1)).findComicsMarkedForPurging();
}
}

0 comments on commit 6fa7bcc

Please sign in to comment.