Talk about maxwell's Scripting

order

This paper mainly studies maxwell's Scripting

Scripting

maxwell-1.25.1/src/main/java/com/zendesk/maxwell/scripting/Scripting.java

public class Scripting {
	static final Logger LOGGER = LoggerFactory.getLogger(Scripting.class);

	private final ScriptObjectMirror processRowFunc, processHeartbeatFunc, processDDLFunc;

	private ScriptObjectMirror getFunc(ScriptEngine engine, String fName, String filename) {
		ScriptObjectMirror f = (ScriptObjectMirror) engine.get(fName);
		if ( f == null )
			return null;
		else if ( !f.isFunction() ) {
			throw new RuntimeException("Expected " + fName + " to be a function!");
		} else {
			LOGGER.info("using function " + fName + " from " + filename);
		}
		return f;
	}

	public Scripting(String filename) throws IOException, ScriptException, NoSuchMethodException {
		ScriptEngineManager manager = new ScriptEngineManager();
		ScriptEngine engine = manager.getEngineByName("nashorn");

		String externJS = new String(Files.readAllBytes(Paths.get(filename)));
		engine.put("logger", LOGGER);
		engine.eval(externJS);

		processRowFunc = getFunc(engine, "process_row", filename);
		processHeartbeatFunc = getFunc(engine, "process_heartbeat", filename);
		processDDLFunc = getFunc(engine, "process_ddl", filename);

		if ( processRowFunc == null && processHeartbeatFunc == null && processDDLFunc == null )
			LOGGER.warn("expected " + filename + " to define at least one of: process_row,process_heartbeat,process_ddl");
	}

	public void invoke(RowMap row) {
		if ( row instanceof HeartbeatRowMap && processHeartbeatFunc != null )
			processHeartbeatFunc.call(null, new WrappedHeartbeatMap((HeartbeatRowMap) row));
		else if ( row instanceof DDLMap && processDDLFunc != null )
			processDDLFunc.call(null, new WrappedDDLMap((DDLMap) row));
		else if ( row instanceof RowMap && processRowFunc != null )
			processRowFunc.call(null, new WrappedRowMap(row));
	}

	private static ThreadLocal<ScriptEngine> stringifyEngineThreadLocal = ThreadLocal.withInitial(() -> {
		ScriptEngineManager manager = new ScriptEngineManager();
		return manager.getEngineByName("nashorn");
	});

	public static String stringify(ScriptObjectMirror mirror) throws ScriptException {
		ScriptObjectMirror json = (ScriptObjectMirror) stringifyEngineThreadLocal.get().eval("JSON");
		return (String) json.callMember("stringify", mirror);
	}
}
  • Scripting defines the processRowFunc, processHeartbeatFunc, and processDDLFunc attributes; its constructor receives the filename parameter, which creates a ScriptEngineManager, and then gets the ScriptEngine named nashorn, and then gets the externJS through filename, and executes engine.eval(externJS). After that, it initializes processRowFunc, processHeartbeatFunc, and processddlfu through the getFunc method NC; its getFunc method obtains ScriptObjectMirror through engine.get(fName); its invoke method executes processHeartbeatFunc.call for HeartbeatRowMap, processDDLFunc.call for DDLMap, and processRowFunc.call for RowMap

MaxwellConfig

maxwell-1.25.1/src/main/java/com/zendesk/maxwell/MaxwellConfig.java

public class MaxwellConfig extends AbstractConfig {
	static final Logger LOGGER = LoggerFactory.getLogger(MaxwellConfig.class);

	//......

	public String javascriptFile;
	public Scripting scripting;

	//......

	public void validate() {
		validatePartitionBy();
		validateFilter();

		//......

		if ( this.javascriptFile != null ) {
			try {
				this.scripting = new Scripting(this.javascriptFile);
			} catch ( Exception e ) {
				LOGGER.error("Error setting up javascript: ", e);
				System.exit(1);
			}
		}
	}

	//......

}
  • The validate method of Maxwell config will create Scripting when the JavaScript file is not null. If there is an exception, execute System.exit(1)

Summary

Scripting defines the processRowFunc, processHeartbeatFunc, and processDDLFunc attributes; its constructor receives the filename parameter, which creates a ScriptEngineManager, and then gets the ScriptEngine named nashorn, and then gets the externJS through filename, and executes engine.eval(externJS). After that, it initializes processRowFunc, processHeartbeatFunc, and processddlfu through the getFunc method NC; its getFunc method obtains ScriptObjectMirror through engine.get(fName); its invoke method executes processHeartbeatFunc.call for HeartbeatRowMap, processDDLFunc.call for DDLMap, and processRowFunc.call for RowMap

doc

Tags: Programming Java JSON Javascript

Posted on Sun, 10 May 2020 10:38:00 -0400 by matthewst