-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Job for reindexing elastic indexes & move index aliases #258
Changes from 5 commits
6f1aa47
825dcf8
18d16b6
74b9459
365fa66
31ce9a9
4841ede
78dce20
d6d5187
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,102 @@ | ||||||
/* | ||||||
* 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.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.db.es.Elastic; | ||||||
import sirius.db.mixing.EntityDescriptor; | ||||||
import sirius.kernel.di.std.Part; | ||||||
import sirius.kernel.di.std.Register; | ||||||
import sirius.kernel.health.Exceptions; | ||||||
import sirius.kernel.nls.NLS; | ||||||
|
||||||
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) | ||||||
public class MoveIndexAliasJobFactory extends BatchProcessJobFactory { | ||||||
@Part | ||||||
private Elastic elastic; | ||||||
|
||||||
private ElasticEntityDescriptorParameter entityDescriptorParameter = null; | ||||||
private StringParameter stringParameter = null; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||
|
||||||
@Override | ||||||
protected String createProcessTitle(Map<String, String> context) { | ||||||
return "MoveIndexAlias"; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. something like Strings.apply("Movin Elasticsearch Index %s to %s, ....) - would be very nice |
||||||
} | ||||||
|
||||||
@Override | ||||||
protected Class<? extends DistributedTaskExecutor> getExecutor() { | ||||||
return DefaultBatchProcessTaskExecutor.class; | ||||||
} | ||||||
|
||||||
@Override | ||||||
protected void executeTask(ProcessContext process) throws Exception { | ||||||
String destination = process.getParameter(stringParameter) | ||||||
.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) { | ||||||
if (stringParameter == null) { | ||||||
stringParameter = new StringParameter("destination", NLS.get("MoveIndexAliasJobFactory.destinationParameter")); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do not cache the parameter here, as NLS.get is dependent on the user locale - so the first user would determine the parameter name for all successive calls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. simply use collector.accept(new StringParameter(...).markRequired()) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or even better - initialize the fields directly and uses a constant for label as it will be auto translated |
||||||
stringParameter.markRequired(); | ||||||
} | ||||||
|
||||||
if (entityDescriptorParameter == null) { | ||||||
entityDescriptorParameter = new ElasticEntityDescriptorParameter("ed", NLS.get("MoveIndexAliasJobFactory.descriptorParameter")); | ||||||
entityDescriptorParameter.markRequired(); | ||||||
} | ||||||
|
||||||
parameterCollector.accept(stringParameter); | ||||||
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 "MAINTENANCE"; | ||||||
} | ||||||
|
||||||
@Nonnull | ||||||
@Override | ||||||
public String getName() { | ||||||
return "move-index-alias"; | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
/* | ||
* 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.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.db.es.Elastic; | ||
import sirius.db.es.IndexMappings; | ||
import sirius.db.mixing.EntityDescriptor; | ||
import sirius.kernel.di.std.Part; | ||
import sirius.kernel.di.std.Register; | ||
import sirius.kernel.health.Exceptions; | ||
import sirius.kernel.nls.NLS; | ||
|
||
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) | ||
public class ReindexJobFactory extends BatchProcessJobFactory { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Permission(TenantUserManager.PERMISSION_SYSTEM_TENANT) |
||
|
||
@Part | ||
private Elastic elastic; | ||
|
||
@Part | ||
private IndexMappings mappings; | ||
|
||
private ElasticEntityDescriptorParameter entityDescriptorParameter = null; | ||
|
||
@Override | ||
protected String createProcessTitle(Map<String, String> context) { | ||
return "Reindex"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s.a. |
||
} | ||
|
||
@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) { | ||
if (entityDescriptorParameter == null) { | ||
entityDescriptorParameter = new ElasticEntityDescriptorParameter("ed", NLS.get("ReindexJobFactory.descriptorParameter")); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. s.a. |
||
entityDescriptorParameter.markRequired(); | ||
} | ||
|
||
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 "MAINTENANCE"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 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); | ||
} | ||
} |
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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.