Skip to content

Commit

Permalink
Merge pull request #258 from scireum/tba/reindex-aliasing
Browse files Browse the repository at this point in the history
Job for reindexing elastic indexes & move index aliases
  • Loading branch information
andyHa authored Feb 18, 2019
2 parents 3893d11 + d6d5187 commit f7a512f
Show file tree
Hide file tree
Showing 7 changed files with 353 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<properties>
<sirius.kernel>12.5</sirius.kernel>
<sirius.web>20.4</sirius.web>
<sirius.db>5.4</sirius.db>
<sirius.db>6.1</sirius.db>
</properties>

<dependencies>
Expand Down
108 changes: 108 additions & 0 deletions src/main/java/sirius/biz/elastic/reindex/MoveIndexAliasJobFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - info@scireum.de
*/

package sirius.biz.elastic.reindex;

import sirius.biz.cluster.work.DistributedTaskExecutor;
import sirius.biz.jobs.JobCategory;
import sirius.biz.jobs.JobFactory;
import sirius.biz.jobs.batch.BatchProcessJobFactory;
import sirius.biz.jobs.batch.DefaultBatchProcessTaskExecutor;
import sirius.biz.jobs.params.ElasticEntityDescriptorParameter;
import sirius.biz.jobs.params.Parameter;
import sirius.biz.jobs.params.StringParameter;
import sirius.biz.process.ProcessContext;
import sirius.biz.tenants.TenantUserManager;
import sirius.db.es.Elastic;
import sirius.db.mixing.EntityDescriptor;
import sirius.db.mixing.Mixing;
import sirius.kernel.commons.Strings;
import sirius.kernel.di.std.Part;
import sirius.kernel.di.std.Register;
import sirius.kernel.health.Exceptions;
import sirius.web.security.Permission;

import javax.annotation.Nonnull;
import java.util.Map;
import java.util.function.Consumer;

/**
* Implements a job which moves the alias which marks an active index to a desired destination index.
*/
@Register(classes = JobFactory.class)
@Permission(TenantUserManager.PERMISSION_SYSTEM_TENANT)
public class MoveIndexAliasJobFactory extends BatchProcessJobFactory {

@Part
private Elastic elastic;

@Part
private Mixing mixing;

private ElasticEntityDescriptorParameter entityDescriptorParameter =
(ElasticEntityDescriptorParameter) new ElasticEntityDescriptorParameter("ed",
"$MoveIndexAliasJobFactory.descriptorParameter")
.markRequired();
private StringParameter destinationParameter =
new StringParameter("destination", "$MoveIndexAliasJobFactory.destinationParameter").markRequired();

@Override
protected String createProcessTitle(Map<String, String> context) {
return Strings.apply("Moving active elasticsearch alias from index '%s' to '%s'",
Strings.join(elastic.getLowLevelClient()
.getIndicesForAlias(mixing.getDescriptor(context.get("ed"))), ","),
context.get("destination"));
}

@Override
protected Class<? extends DistributedTaskExecutor> getExecutor() {
return DefaultBatchProcessTaskExecutor.class;
}

@Override
protected void executeTask(ProcessContext process) throws Exception {
String destination = process.getParameter(destinationParameter)
.orElseThrow(() -> Exceptions.handle()
.withSystemErrorMessage("No destination index given!")
.handle());
EntityDescriptor ed = process.getParameter(entityDescriptorParameter)
.orElseThrow(() -> Exceptions.handle()
.withSystemErrorMessage(
"Can't resolve entity-descriptor.")
.handle());

process.log(elastic.getLowLevelClient().moveActiveAlias(ed, destination).toJSONString());
}

@Override
protected void collectParameters(Consumer<Parameter<?, ?>> parameterCollector) {
parameterCollector.accept(destinationParameter);
parameterCollector.accept(entityDescriptorParameter);
}

@Override
protected boolean hasPresetFor(Object targetObject) {
return false;
}

@Override
protected void computePresetFor(Object targetObject, Map<String, Object> preset) {
// nothing to do yet
}

@Override
public String getCategory() {
return JobCategory.CATEGORY_MISC;
}

@Nonnull
@Override
public String getName() {
return "move-index-alias";
}
}
116 changes: 116 additions & 0 deletions src/main/java/sirius/biz/elastic/reindex/ReindexJobFactory.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - info@scireum.de
*/

package sirius.biz.elastic.reindex;

import sirius.biz.cluster.work.DistributedTaskExecutor;
import sirius.biz.jobs.JobCategory;
import sirius.biz.jobs.JobFactory;
import sirius.biz.jobs.batch.BatchProcessJobFactory;
import sirius.biz.jobs.batch.DefaultBatchProcessTaskExecutor;
import sirius.biz.jobs.params.ElasticEntityDescriptorParameter;
import sirius.biz.jobs.params.Parameter;
import sirius.biz.process.ProcessContext;
import sirius.biz.tenants.TenantUserManager;
import sirius.db.es.Elastic;
import sirius.db.es.IndexMappings;
import sirius.db.mixing.EntityDescriptor;
import sirius.kernel.commons.Strings;
import sirius.kernel.di.std.Part;
import sirius.kernel.di.std.Register;
import sirius.kernel.health.Exceptions;
import sirius.kernel.nls.NLS;
import sirius.web.security.Permission;

import javax.annotation.Nonnull;
import java.time.LocalDate;
import java.util.Map;
import java.util.function.Consumer;

/**
* Implements a job which reindexes a given index in elastic.
*/
@Register(classes = JobFactory.class)
@Permission(TenantUserManager.PERMISSION_SYSTEM_TENANT)
public class ReindexJobFactory extends BatchProcessJobFactory {

@Part
private Elastic elastic;

@Part
private IndexMappings mappings;

private ElasticEntityDescriptorParameter entityDescriptorParameter =
(ElasticEntityDescriptorParameter) new ElasticEntityDescriptorParameter("ed",
"$ReindexJobFactory.descriptorParameter")
.markRequired();

@Override
protected String createProcessTitle(Map<String, String> context) {
return Strings.apply("Reindexing mapping '%s'", context.get("ed"));
}

@Override
protected Class<? extends DistributedTaskExecutor> getExecutor() {
return DefaultBatchProcessTaskExecutor.class;
}

@Override
protected void executeTask(ProcessContext process) throws Exception {
EntityDescriptor ed = process.getParameter(entityDescriptorParameter)
.orElseThrow(() -> Exceptions.handle()
.withSystemErrorMessage(
"Can't resolve entity-descriptor.")
.handle());

String nextIndex = determineNextIndexName(ed);
mappings.createMapping(ed, nextIndex);
process.log("Created index " + nextIndex);
process.log(elastic.getLowLevelClient().reindex(ed, nextIndex).toJSONString());
}

private String determineNextIndexName(EntityDescriptor ed) {
String nextIndexName = ed.getRelationName() + "-" + NLS.toMachineString(LocalDate.now());
int run = 0;

while (run++ < 10) {
if (!elastic.getLowLevelClient().indexExists(nextIndexName)) {
return nextIndexName;
}
nextIndexName = ed.getRelationName() + "-" + NLS.toMachineString(LocalDate.now()) + "-" + run;
}

throw Exceptions.handle().withSystemErrorMessage("Couldn't find a unique index name after 10 runs!").handle();
}

@Override
protected void collectParameters(Consumer<Parameter<?, ?>> parameterCollector) {
parameterCollector.accept(entityDescriptorParameter);
}

@Override
protected boolean hasPresetFor(Object targetObject) {
return false;
}

@Override
protected void computePresetFor(Object targetObject, Map<String, Object> preset) {
// nothing to do yet
}

@Override
public String getCategory() {
return JobCategory.CATEGORY_MISC;
}

@Nonnull
@Override
public String getName() {
return "reindex-index-mapping";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - info@scireum.de
*/

package sirius.biz.jobs.params;

import sirius.db.es.ElasticEntity;
import sirius.db.mixing.EntityDescriptor;
import sirius.db.mixing.Mixing;

import java.util.List;
import java.util.stream.Collectors;

/**
* Provides a parameter which accepts {@link EntityDescriptor} which represent {@link ElasticEntity elastic entities}.
*/
public class ElasticEntityDescriptorParameter extends EntityDescriptorParameter {

public ElasticEntityDescriptorParameter(String name, String label) {
super(name, label);
}

/**
* Enumerates all {@link EntityDescriptor descriptors} which represent {@link ElasticEntity elastic entites} known to the system.
*
* @return the list of value defined by the enum type
*/
public List<String> getValues() {
return mixing.getDesciptors()
.stream()
.filter(entityDescriptor -> ElasticEntity.class.isAssignableFrom(entityDescriptor.getType()))
.map(entityDescriptor -> Mixing.getNameForType(entityDescriptor.getType()))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - info@scireum.de
*/

package sirius.biz.jobs.params;

import sirius.db.mixing.EntityDescriptor;
import sirius.db.mixing.Mixing;
import sirius.kernel.commons.Value;
import sirius.kernel.di.std.Part;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
* Provides a parameter which accepts {@link EntityDescriptor}.
*/
public class EntityDescriptorParameter extends Parameter<EntityDescriptor, EntityDescriptorParameter> {

@Part
protected static Mixing mixing;

public EntityDescriptorParameter(String name, String label) {
super(name, label);
}

@Override
public String getTemplateName() {
return "/templates/jobs/params/entity-descriptors.html.pasta";
}

/**
* Enumerates all {@link EntityDescriptor descriptors} known to the system.
*
* @return the list of value defined by the enum type
*/
public List<String> getValues() {
return mixing.getDesciptors()
.stream()
.map(entityDescriptor -> Mixing.getNameForType(entityDescriptor.getType()))
.collect(Collectors.toList());
}

@Override
protected String checkAndTransformValue(Value input) {
if (input.isEmptyString()) {
return null;
}

EntityDescriptor ed = mixing.getDescriptor(input.getString());

if (ed == null) {
return null;
}

return input.getString();
}

@Override
protected Optional<EntityDescriptor> resolveFromString(Value input) {
if (input.isEmptyString()) {
return Optional.empty();
}
EntityDescriptor ed = mixing.getDescriptor(input.getString());
return Optional.ofNullable(ed);
}
}
3 changes: 3 additions & 0 deletions src/main/resources/biz_de.properties
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ Model.priority = Sortierung
Model.security = Sicherheit
Model.tenant = Mandant
Model.userAccount = Anwender
MoveIndexAliasJobFactory.descriptorParameter = Schema
MoveIndexAliasJobFactory.destinationParameter = Zielindex
Parameter.invalidValue = Fehler im Parameter ${name}: ${message}
Parameter.required = Der Parameter ${name} muss gefüllt sein.
PersonData.birthday = Geburtstag
Expand Down Expand Up @@ -237,6 +239,7 @@ ProcessState.TERMINATED = Beendet
ProfileController.invalidOldPassword = Das alte Password ist inkorrekt.
ProfileController.myProfile = Mein Profil
ProfileController.userProfile = Anwenderprofil
ReindexJobFactory.descriptorParameter = Schema
Role.administrator = Administrator
Role.administrator.description = Ermöglicht dem Anwender Systemeinstellungen abzuändern.
Role.file-manager = Dateien verwalten
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<i:arg type="sirius.biz.jobs.params.EntityDescriptorParameter" name="param"/>
<i:arg type="Map" name="context"/>

<w:singleSelect span="@param.getSpan()"
smallSpan="@param.getSmallSpan()"
name="@param.getName()"
label="@param.getLabel()"
help="@param.getDescription()"
optional="@!param.isRequired()"
required="@param.isRequired()">
<i:for var="value" type="String" items="@param.getValues()">
<option value="@value" @selected="value == param.get(context).orElse(null)">@value</option>
</i:for>
</w:singleSelect>

0 comments on commit f7a512f

Please sign in to comment.