diff --git a/lib/Tumblr/StreamBuilder/Codec/BinaryCodec.php b/lib/Tumblr/StreamBuilder/Codec/BinaryCodec.php index 04727a8..f3a4eef 100644 --- a/lib/Tumblr/StreamBuilder/Codec/BinaryCodec.php +++ b/lib/Tumblr/StreamBuilder/Codec/BinaryCodec.php @@ -103,9 +103,15 @@ public function __construct( /** * @inheritDoc */ - public function encode(Templatable $obj): string + public function encode($obj): string { - $json = Helpers::json_encode($obj->to_template()); + if ($obj instanceof Templatable) { + $json = Helpers::json_encode($obj->to_template()); + } elseif (is_string($obj)) { + $json = $obj; + } else { + throw new \InvalidArgumentException(sprintf("%s type is not supported", get_class($obj))); + } $compressed = gzdeflate($json); $encrypted = openssl_encrypt($compressed, self::CIPHER, $this->encrypt_key, 0, $this->initial_vector); $signature = $this->compute_signature($encrypted); diff --git a/lib/Tumblr/StreamBuilder/Codec/CacheCodec.php b/lib/Tumblr/StreamBuilder/Codec/CacheCodec.php index 5e364f4..e38ea98 100644 --- a/lib/Tumblr/StreamBuilder/Codec/CacheCodec.php +++ b/lib/Tumblr/StreamBuilder/Codec/CacheCodec.php @@ -41,6 +41,12 @@ final class CacheCodec extends Codec */ public const SERIALIZATION_TYPE_JSON = 'JSON'; + /** + * Cache content from an already-serialized string of JSON. + * @var string + */ + public const SERIALIZATION_TYPE_JSON_STRING = 'JSON_STRING'; + /** * Cache content serialized/deserialized by doing serialize/unserialize * @var string @@ -80,12 +86,15 @@ public function __construct( /** * @inheritDoc */ - public function encode(Templatable $obj): string + public function encode($obj): string { switch ($this->serialization_type) { case self::SERIALIZATION_TYPE_JSON: $serialized = Helpers::json_encode($obj->to_template()); break; + case self::SERIALIZATION_TYPE_JSON_STRING: + $serialized = $obj; + break; case self::SERIALIZATION_TYPE_PHP_OBJECT: $serialized = serialize($obj); break; diff --git a/lib/Tumblr/StreamBuilder/Codec/Codec.php b/lib/Tumblr/StreamBuilder/Codec/Codec.php index d42cbf4..1787814 100644 --- a/lib/Tumblr/StreamBuilder/Codec/Codec.php +++ b/lib/Tumblr/StreamBuilder/Codec/Codec.php @@ -81,11 +81,11 @@ public function __construct(CacheProvider $cache_provider = null) } /** - * Encode a templatable object. - * @param Templatable $obj The object to encode. + * Encode an object. + * @param Templatable|string $obj The object to encode, or pre-encoded object. * @return string The encoded bytes string. */ - abstract public function encode(Templatable $obj): string; + abstract public function encode($obj): string; /** * Decode an encoded templatable object. diff --git a/lib/Tumblr/StreamBuilder/StreamCursors/StreamCursor.php b/lib/Tumblr/StreamBuilder/StreamCursors/StreamCursor.php index e102237..494a6c2 100644 --- a/lib/Tumblr/StreamBuilder/StreamCursors/StreamCursor.php +++ b/lib/Tumblr/StreamBuilder/StreamCursors/StreamCursor.php @@ -171,13 +171,12 @@ public static function encode( $current_user_id ); - $encoded = $binary_codec->encode($cursor); + $json = Helpers::json_encode($cursor->to_template()); + $encoded = $binary_codec->encode($json); $encoded = Helpers::base64UrlEncode($encoded); $cursor_size = strlen($encoded); $context = $context ?? 'unknown'; - StreamBuilder::getDependencyBag()->getLog() - ->histogramTick('cursor_size', $context, ($cursor_size / 1000.0)); if (($cache_provider instanceof CacheProvider) && ($cursor_size > $cache_size_threshold)) { StreamBuilder::getDependencyBag()->getLog() @@ -185,13 +184,21 @@ public static function encode( $cache_codec = new CacheCodec( $cache_provider, CacheProvider::OBJECT_TYPE_CURSOR, - CacheCodec::SERIALIZATION_TYPE_JSON + CacheCodec::SERIALIZATION_TYPE_JSON_STRING ); - $encoded = $cache_codec->encode($cursor); + $encoded = $cache_codec->encode($json); // base64 url encode cache encoded as well, to line up with binary codec encoded logic. $encoded = Helpers::base64UrlEncode($encoded); + + // This is an implementation detail, but the CacheCodec does not base64 encode the payload before + // writing to cache, so the original cursor_size is misleading. Base64 encoding can increase the + // payload size by 33%. + $cursor_size = strlen($json); } + StreamBuilder::getDependencyBag()->getLog() + ->histogramTick('cursor_size', $context, ($cursor_size / 1000.0)); + return $encoded; }