Details
-
Improvement
-
Status: Closed
-
Major
-
Resolution: Information Provided
-
3.3.8
-
None
-
None
Description
Graph Providers like AWS, Alibaba both use withSideEffect to provide vendor related abilities.
A simple example like:
g.withSideEffect("GDB#withStrategies","DetachedElementStrategy").otherSteps()
This will add SideEffectStrategy to traversalSource and apply later before traversal execute. but it's logic is too simple(just put k, v into traversal.getSideEffects() and let traversal to use when executing ):
@Override public void apply(final Traversal.Admin<?, ?> traversal) { if (traversal.getParent() instanceof EmptyStep) { this.sideEffects.forEach(triplet -> traversal.getSideEffects().register(triplet.getValue0(), triplet.getValue1(), triplet.getValue2())); } }
More general, we need to provide a more powerful and flexible ability (some hooks ability) to allow provider‘s private functions be called,a sample i thinks looks like as follows:
/* * (C) 2019-present Alibaba Group Holding Limited. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * File: WithSideEffectOptimizerStrategy.java * * Authors: * zhoujian <qiaogong.zj@alibaba-inc.com> * 2019-09-22 17:37 - initial release */ package com.alibaba.graphdb.core.optimize.strategy; import com.google.common.collect.Sets; import org.apache.tinkerpop.gremlin.process.traversal.Traversal; import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy; import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SideEffectStrategy; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.function.BiConsumer; /** * gdb specific optimizer here */ public class WithSideEffectOptimizerStrategy extends AbstractGraphDbTraversalStrategy { private static final WithSideEffectOptimizerStrategy INSTANCE = new WithSideEffectOptimizerStrategy(); private final Collection<Optimizer> initials = new ArrayList<>(); public static WithSideEffectOptimizerStrategy instance() { return INSTANCE; } public WithSideEffectOptimizerStrategy() { initials.add(Optimizer.withStrategies.instance()); } /** * (non-Javadoc) * @see org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy#applyPrior() */ @SuppressWarnings("unchecked") @Override public Set<Class<? extends ProviderOptimizationStrategy>> applyPrior() { return (Set) Sets.newHashSet(SideEffectStrategy.class); } @Override public void apply(final Traversal.Admin<?, ?> traversal) { initials.forEach(optimizer -> optimizer.accept(traversal, optimizer.getAccessor())); } private enum Optimizer implements BiConsumer<Traversal.Admin<?, ?>, String> { withStrategies { @Override public Optimizer instance() { classMap.put(DetachedElementStrategy.class.getSimpleName(), DetachedElementStrategy.class.getCanonicalName()); return this; } @Override public String getAccessor () { return WITH_STRATEGY; } @Override public void accept(final Traversal.Admin<?, ?> traversal, final String key) { try { String strategyName = classMap.get(String.valueOf(traversal.getSideEffects().getSupplier(key).get())); if (strategyName != null) { ((TraversalStrategy) Class.forName(strategyName).newInstance()).apply(traversal); } } catch (Exception e) { return; } } private final Map<String, String> classMap = new LinkedHashMap<>(); }; private static final String WITH_STRATEGY = gdbSpecificSideEffect("withStrategies"); @Override public abstract void accept(final Traversal.Admin<?, ?> traversal, final String key); public abstract String getAccessor(); public abstract Optimizer instance(); private static String gdbSpecificSideEffect(final String key) { return "GDB#" + key; } } }
In the above example, when people determine to use different provider related strategy, it could by easily merge into WithSideEffectOptimizerStrategy. Of course the above code is just a demo, we may have many different kinds of Optimizer here。
If we add this feature, so withSideEffect may take effect in two stages:
- when a certain traversal step executing, default case.
- when withSideEffect step are parsing, different graph provider may implement different logic here.
All kinds of opinions are welcomed !