Add Dry Run option to clean task (#1081)

This commit is contained in:
bnkai
2021-01-29 06:03:34 +02:00
committed by GitHub
parent 203fc3e4b2
commit df8675c2e7
9 changed files with 60 additions and 21 deletions

View File

@@ -26,8 +26,8 @@ mutation MetadataAutoTag($input: AutoTagMetadataInput!) {
metadataAutoTag(input: $input) metadataAutoTag(input: $input)
} }
mutation MetadataClean { mutation MetadataClean($input: CleanMetadataInput!) {
metadataClean metadataClean(input: $input)
} }
mutation MigrateHashNaming { mutation MigrateHashNaming {

View File

@@ -213,7 +213,7 @@ type Mutation {
"""Start auto-tagging. Returns the job ID""" """Start auto-tagging. Returns the job ID"""
metadataAutoTag(input: AutoTagMetadataInput!): String! metadataAutoTag(input: AutoTagMetadataInput!): String!
"""Clean metadata. Returns the job ID""" """Clean metadata. Returns the job ID"""
metadataClean: String! metadataClean(input: CleanMetadataInput!): String!
"""Migrate generated files for the current hash naming""" """Migrate generated files for the current hash naming"""
migrateHashNaming: String! migrateHashNaming: String!

View File

@@ -44,6 +44,11 @@ input ScanMetadataInput {
scanGenerateSprites: Boolean! scanGenerateSprites: Boolean!
} }
input CleanMetadataInput {
"""Do a dry run. Don't delete any files"""
dryRun: Boolean!
}
input AutoTagMetadataInput { input AutoTagMetadataInput {
"""IDs of performers to tag files with, or "*" for all""" """IDs of performers to tag files with, or "*" for all"""
performers: [String!] performers: [String!]

View File

@@ -70,8 +70,8 @@ func (r *mutationResolver) MetadataAutoTag(ctx context.Context, input models.Aut
return "todo", nil return "todo", nil
} }
func (r *mutationResolver) MetadataClean(ctx context.Context) (string, error) { func (r *mutationResolver) MetadataClean(ctx context.Context, input models.CleanMetadataInput) (string, error) {
manager.GetInstance().Clean() manager.GetInstance().Clean(input)
return "todo", nil return "todo", nil
} }

View File

@@ -783,7 +783,7 @@ func (s *singleton) autoTagTags(tagIds []string) {
} }
} }
func (s *singleton) Clean() { func (s *singleton) Clean(input models.CleanMetadataInput) {
if s.Status.Status != Idle { if s.Status.Status != Idle {
return return
} }
@@ -803,8 +803,13 @@ func (s *singleton) Clean() {
gqb := r.Gallery() gqb := r.Gallery()
logger.Infof("Starting cleaning of tracked files") logger.Infof("Starting cleaning of tracked files")
if input.DryRun {
logger.Infof("Running in Dry Mode")
}
var err error var err error
scenes, err = qb.All() scenes, err = qb.All()
if err != nil { if err != nil {
return errors.New("failed to fetch list of scenes for cleaning") return errors.New("failed to fetch list of scenes for cleaning")
} }
@@ -853,7 +858,7 @@ func (s *singleton) Clean() {
Scene: scene, Scene: scene,
fileNamingAlgorithm: fileNamingAlgo, fileNamingAlgorithm: fileNamingAlgo,
} }
go task.Start(&wg) go task.Start(&wg, input.DryRun)
wg.Wait() wg.Wait()
} }
@@ -875,7 +880,7 @@ func (s *singleton) Clean() {
TxnManager: s.TxnManager, TxnManager: s.TxnManager,
Image: img, Image: img,
} }
go task.Start(&wg) go task.Start(&wg, input.DryRun)
wg.Wait() wg.Wait()
} }
@@ -897,7 +902,7 @@ func (s *singleton) Clean() {
TxnManager: s.TxnManager, TxnManager: s.TxnManager,
Gallery: gallery, Gallery: gallery,
} }
go task.Start(&wg) go task.Start(&wg, input.DryRun)
wg.Wait() wg.Wait()
} }

View File

@@ -21,18 +21,18 @@ type CleanTask struct {
fileNamingAlgorithm models.HashAlgorithm fileNamingAlgorithm models.HashAlgorithm
} }
func (t *CleanTask) Start(wg *sync.WaitGroup) { func (t *CleanTask) Start(wg *sync.WaitGroup, dryRun bool) {
defer wg.Done() defer wg.Done()
if t.Scene != nil && t.shouldCleanScene(t.Scene) { if t.Scene != nil && t.shouldCleanScene(t.Scene) && !dryRun {
t.deleteScene(t.Scene.ID) t.deleteScene(t.Scene.ID)
} }
if t.Gallery != nil && t.shouldCleanGallery(t.Gallery) { if t.Gallery != nil && t.shouldCleanGallery(t.Gallery) && !dryRun {
t.deleteGallery(t.Gallery.ID) t.deleteGallery(t.Gallery.ID)
} }
if t.Image != nil && t.shouldCleanImage(t.Image) { if t.Image != nil && t.shouldCleanImage(t.Image) && !dryRun {
t.deleteImage(t.Image.ID) t.deleteImage(t.Image.ID)
} }
} }

View File

@@ -7,6 +7,7 @@
* Allow configuration of visible navbar items. * Allow configuration of visible navbar items.
### 🎨 Improvements ### 🎨 Improvements
* Add dry-run option for Clean task.
* Refresh UI when changing custom CSS options. * Refresh UI when changing custom CSS options.
* Add batch deleting of performers, tags, studios, and movies. * Add batch deleting of performers, tags, studios, and movies.
* Reset cache after scan/clean to ensure scenes are updated. * Reset cache after scan/clean to ensure scenes are updated.

View File

@@ -41,6 +41,7 @@ export const SettingsTasksPanel: React.FC = () => {
const [scanGenerateSprites, setScanGenerateSprites] = useState<boolean>( const [scanGenerateSprites, setScanGenerateSprites] = useState<boolean>(
false false
); );
const [cleanDryRun, setCleanDryRun] = useState<boolean>(false);
const [ const [
scanGenerateImagePreviews, scanGenerateImagePreviews,
setScanGenerateImagePreviews, setScanGenerateImagePreviews,
@@ -132,12 +133,31 @@ export const SettingsTasksPanel: React.FC = () => {
function onClean() { function onClean() {
setIsCleanAlertOpen(false); setIsCleanAlertOpen(false);
mutateMetadataClean().then(() => { mutateMetadataClean({
dryRun: cleanDryRun,
}).then(() => {
jobStatus.refetch(); jobStatus.refetch();
}); });
} }
function renderCleanAlert() { function renderCleanAlert() {
let msg;
if (cleanDryRun) {
msg = (
<p>
Dry Mode selected. No actual deleting will take place, only logging.
</p>
);
} else {
msg = (
<p>
Are you sure you want to Clean? This will delete database information
and generated content for all scenes and galleries that are no longer
found in the filesystem.
</p>
);
}
return ( return (
<Modal <Modal
show={isCleanAlertOpen} show={isCleanAlertOpen}
@@ -145,11 +165,7 @@ export const SettingsTasksPanel: React.FC = () => {
accept={{ text: "Clean", variant: "danger", onClick: onClean }} accept={{ text: "Clean", variant: "danger", onClick: onClean }}
cancel={{ onClick: () => setIsCleanAlertOpen(false) }} cancel={{ onClick: () => setIsCleanAlertOpen(false) }}
> >
<p> {msg}
Are you sure you want to Clean? This will delete database information
and generated content for all scenes and galleries that are no longer
found in the filesystem.
</p>
</Modal> </Modal>
); );
} }
@@ -442,6 +458,17 @@ export const SettingsTasksPanel: React.FC = () => {
<h5>Generated Content</h5> <h5>Generated Content</h5>
<GenerateButton /> <GenerateButton />
<hr />
<h5>Maintenance</h5>
<Form.Group>
<Form.Check
id="clean-dryrun"
checked={cleanDryRun}
label="Only perform a dry run. Don't remove anything"
onChange={() => setCleanDryRun(!cleanDryRun)}
/>
</Form.Group>
<Form.Group> <Form.Group>
<Button <Button
id="clean" id="clean"

View File

@@ -826,9 +826,10 @@ export const mutateMetadataGenerate = (input: GQL.GenerateMetadataInput) =>
variables: { input }, variables: { input },
}); });
export const mutateMetadataClean = () => export const mutateMetadataClean = (input: GQL.CleanMetadataInput) =>
client.mutate<GQL.MetadataCleanMutation>({ client.mutate<GQL.MetadataCleanMutation>({
mutation: GQL.MetadataCleanDocument, mutation: GQL.MetadataCleanDocument,
variables: { input },
}); });
export const mutateMigrateHashNaming = () => export const mutateMigrateHashNaming = () =>