Repository: incubator-zeppelin Updated Branches: refs/heads/master d9ac131e1 -> 28d30b4d4
[ZEPPELIN-420] Improve notebook clone behavior This PR handles two issues with notebook clone behavior. * If same paragraphs from original notebook and cloned notebook run at the same time, both paragraphs can be in `RUNNING` status. And clone notebook's paragraph stays in running status until restart Zeppelin server because two paragraphs have same paragraph id and job id:  After:  * Copy paragraph status(RUNNING, PENDING):  After:  Author: Mina Lee <[email protected]> Closes #432 from minahlee/ZEPPELIN-420 and squashes the following commits: 8eb7973 [Mina Lee] [ZEPPELIN-420] Add clone note test 102f8ea [Mina Lee] [ZEPPELIN-420] Improve notebook clone behavior Project: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/commit/28d30b4d Tree: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/tree/28d30b4d Diff: http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/diff/28d30b4d Branch: refs/heads/master Commit: 28d30b4d47d9e3267ae991ba0bece461a3a83e92 Parents: d9ac131 Author: Mina Lee <[email protected]> Authored: Sun Nov 15 21:32:59 2015 +0900 Committer: Lee moon soo <[email protected]> Committed: Wed Nov 18 12:46:59 2015 +0900 ---------------------------------------------------------------------- .../java/org/apache/zeppelin/notebook/Note.java | 29 +++++++++++++++++--- .../org/apache/zeppelin/notebook/Notebook.java | 5 ++-- .../org/apache/zeppelin/notebook/Paragraph.java | 14 +--------- .../apache/zeppelin/notebook/NotebookTest.java | 21 ++++++++++++++ 4 files changed, 49 insertions(+), 20 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/28d30b4d/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java index 033039c..89a72b5 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java @@ -28,9 +28,11 @@ import java.util.Random; import org.apache.zeppelin.conf.ZeppelinConfiguration; import org.apache.zeppelin.display.AngularObject; import org.apache.zeppelin.display.AngularObjectRegistry; +import org.apache.zeppelin.display.Input; import org.apache.zeppelin.interpreter.Interpreter; import org.apache.zeppelin.interpreter.InterpreterException; import org.apache.zeppelin.interpreter.InterpreterGroup; +import org.apache.zeppelin.interpreter.InterpreterResult; import org.apache.zeppelin.interpreter.InterpreterSetting; import org.apache.zeppelin.notebook.repo.NotebookRepo; import org.apache.zeppelin.notebook.utility.IdHashes; @@ -40,6 +42,8 @@ import org.apache.zeppelin.scheduler.JobListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.gson.Gson; + /** * Binded interpreters for a note */ @@ -144,13 +148,30 @@ public class Note implements Serializable, JobListener { } /** - * Add the paragraph p to the list of paras in note. + * Clone paragraph and add it to note. * - * @param p + * @param srcParagraph */ - public void addParagraph(Paragraph p) { + public void addCloneParagraph(Paragraph srcParagraph) { + Paragraph newParagraph = new Paragraph(this, this, replLoader); + + Map<String, Object> config = new HashMap<>(srcParagraph.getConfig()); + Map<String, Object> param = new HashMap<>(srcParagraph.settings.getParams()); + Map<String, Input> form = new HashMap<>(srcParagraph.settings.getForms()); + Gson gson = new Gson(); + InterpreterResult result = gson.fromJson( + gson.toJson(srcParagraph.getReturn()), + InterpreterResult.class); + + newParagraph.setConfig(config); + newParagraph.settings.setParams(param); + newParagraph.settings.setForms(form); + newParagraph.setText(srcParagraph.getText()); + newParagraph.setTitle(srcParagraph.getTitle()); + newParagraph.setReturn(result, null); + synchronized (paragraphs) { - paragraphs.add(p); + paragraphs.add(newParagraph); } } http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/28d30b4d/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java index 770172a..6624310 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java @@ -141,9 +141,8 @@ public class Notebook { bindInterpretersToNote(newNote.id(), boundInterpreterSettingsIds); List<Paragraph> paragraphs = sourceNote.getParagraphs(); - for (Paragraph para : paragraphs) { - Paragraph p = (Paragraph) para.clone(); - newNote.addParagraph(p); + for (Paragraph p : paragraphs) { + newNote.addCloneParagraph(p); } newNote.persist(); return newNote; http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/28d30b4d/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java index fc3646a..1332f16 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java @@ -276,19 +276,7 @@ public class Paragraph extends Job implements Serializable, Cloneable { @Override public Object clone() throws CloneNotSupportedException { - Paragraph paraClone = (Paragraph) super.clone(); - Map<String, Object> config = new HashMap<>(this.getConfig()); - // Show the editor by default - String hideEditorKey = "editorHide"; - Object object = config.get(hideEditorKey); - if (object != null && object == Boolean.TRUE) { - config.put(hideEditorKey, Boolean.FALSE); - } - Map<String, Object> param = new HashMap<>(this.settings.getParams()); - paraClone.setConfig(config); - paraClone.settings.setParams(param); - paraClone.setTitle(this.getTitle()); - paraClone.setText(this.getText()); + Paragraph paraClone = (Paragraph) this.clone(); return paraClone; } } http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/28d30b4d/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java ---------------------------------------------------------------------- diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java index faad058..5d887e9 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java @@ -18,6 +18,7 @@ package org.apache.zeppelin.notebook; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -222,6 +223,26 @@ public class NotebookTest implements JobListenerFactory{ } @Test + public void testCloneNote() throws IOException, CloneNotSupportedException, + InterruptedException { + Note note = notebook.createNote(); + note.getNoteReplLoader().setInterpreters(factory.getDefaultInterpreterSettingList()); + + final Paragraph p = note.addParagraph(); + p.setText("hello world"); + note.runAll(); + while(p.isTerminated()==false || p.getResult()==null) Thread.yield(); + + p.setStatus(Status.RUNNING); + Note cloneNote = notebook.cloneNote(note.getId(), "clone note"); + Paragraph cp = cloneNote.paragraphs.get(0); + assertEquals(cp.getStatus(), Status.READY); + assertNotEquals(cp.getId(), p.getId()); + assertEquals(cp.text, p.text); + assertEquals(cp.getResult().message(), p.getResult().message()); + } + + @Test public void testAngularObjectRemovalOnNotebookRemove() throws InterruptedException, IOException { // create a note and a paragraph
