[ARVADOS] updated: 07e4083ea451913b988d77e8e4c926da8ad844a4

Git user git at public.curoverse.com
Fri Mar 3 16:23:00 EST 2017


Summary of changes:
 services/api/lib/serializers.rb          | 54 ++++++++++++++++++++------------
 services/api/test/unit/seralizer_test.rb | 22 +++++++++++++
 2 files changed, 56 insertions(+), 20 deletions(-)
 create mode 100644 services/api/test/unit/seralizer_test.rb

       via  07e4083ea451913b988d77e8e4c926da8ad844a4 (commit)
      from  594e00f9311da95f73843f55b6e1c7c3ad55d8df (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 07e4083ea451913b988d77e8e4c926da8ad844a4
Author: Tom Clegg <tom at curoverse.com>
Date:   Fri Mar 3 16:18:10 2017 -0500

    11168: Double-decode serialized fields if database was mangled by downgraded API server.

diff --git a/services/api/lib/serializers.rb b/services/api/lib/serializers.rb
index d7a81e1..41379f3 100644
--- a/services/api/lib/serializers.rb
+++ b/services/api/lib/serializers.rb
@@ -1,40 +1,54 @@
 require 'safe_json'
 
-class HashSerializer
+class Serializer
+  def self.dump(val)
+    SafeJSON.dump(val)
+  end
+
+  def self.legacy_load(s)
+    val = Psych.safe_load(s)
+    if val.is_a? String
+      # If apiserver was downgraded to a YAML-only version after
+      # storing JSON in the database, the old code would have loaded
+      # the JSON document as a plain string, and then YAML-encoded
+      # it when saving it back to the database. It's too late now to
+      # make the old code behave better, but at least we can
+      # gracefully handle the mess it leaves in the database by
+      # double-decoding on the way out.
+      return SafeJSON.load(val)
+    else
+      return val
+    end
+  end
+
   def self.load(s)
     if s.nil?
-      {}
-    elsif s[0] == "{"
+      object_class.new()
+    elsif s[0] == first_json_char
       SafeJSON.load(s)
     elsif s[0..2] == "---"
-      Psych.safe_load(s)
+      legacy_load(s)
     else
       raise "invalid serialized data #{s[0..5].inspect}"
     end
   end
-  def self.dump(h)
-    SafeJSON.dump(h)
+end
+
+class HashSerializer < Serializer
+  def self.first_json_char
+    "{"
   end
+
   def self.object_class
     ::Hash
   end
 end
 
-class ArraySerializer
-  def self.load(s)
-    if s.nil?
-      []
-    elsif s[0] == "["
-      SafeJSON.load(s)
-    elsif s[0..2] == "---"
-      Psych.safe_load(s)
-    else
-      raise "invalid serialized data #{s[0..5].inspect}"
-    end
-  end
-  def self.dump(a)
-    SafeJSON.dump(a)
+class ArraySerializer < Serializer
+  def self.first_json_char
+    "["
   end
+
   def self.object_class
     ::Array
   end
diff --git a/services/api/test/unit/seralizer_test.rb b/services/api/test/unit/seralizer_test.rb
new file mode 100644
index 0000000..4d7ca2a
--- /dev/null
+++ b/services/api/test/unit/seralizer_test.rb
@@ -0,0 +1,22 @@
+require 'test_helper'
+require 'serializers'
+
+class SerializerTest < ActiveSupport::TestCase
+  test 'serialize' do
+    assert_equal('{}', HashSerializer.dump({}))
+    assert_equal('{"foo":"bar"}', HashSerializer.dump(foo: 'bar'))
+    assert_equal('{"foo":"bar"}', HashSerializer.dump('foo' => 'bar'))
+    assert_equal('[]', ArraySerializer.dump([]))
+    assert_equal('["foo",{"foo":"bar"}]',
+                 ArraySerializer.dump(['foo', 'foo' => 'bar']))
+    assert_equal(['foo'],
+                 ArraySerializer.load(ArraySerializer.dump([:foo])))
+    assert_equal([1,'bar'],
+                 ArraySerializer.load(ArraySerializer.dump([1,'bar'])))
+  end
+
+  test 'load array that was saved as json, then mangled by an old version' do
+    assert_equal(['foo'],
+                 ArraySerializer.load(YAML.dump(ArraySerializer.dump(['foo']))))
+  end
+end

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list