Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions lib/Tumblr/StreamBuilder/Codec/BinaryCodec.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,15 @@ public function __construct(
/**
* @inheritDoc
*/
public function encode(Templatable $obj): string
public function encode($obj): string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

damn, need union types 😭

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two functions and adjust call site(s)

{
$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)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should document this in the method's phpdoc, since now it doesn't match the parent class

}
$compressed = gzdeflate($json);
$encrypted = openssl_encrypt($compressed, self::CIPHER, $this->encrypt_key, 0, $this->initial_vector);
$signature = $this->compute_signature($encrypted);
Expand Down
11 changes: 10 additions & 1 deletion lib/Tumblr/StreamBuilder/Codec/CacheCodec.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions lib/Tumblr/StreamBuilder/Codec/Codec.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
17 changes: 12 additions & 5 deletions lib/Tumblr/StreamBuilder/StreamCursors/StreamCursor.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,27 +171,34 @@ 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()
->rateTick('cursor_ops', 'cached');
$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()
Copy link
Contributor

@sanmai sanmai Oct 3, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
StreamBuilder::getDependencyBag()->getLog()
// We are tracking two things simultaneously: a Base64-encoded cursor that goes into a URL
// and a JSON-encoded cursor that persists in the cache.
StreamBuilder::getDependencyBag()->getLog()

Is it going to be a bad idea to add another tick to track just the thing that goes into a URL, and leave the existing tick to track what gets cached?

->histogramTick('cursor_size', $context, ($cursor_size / 1000.0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we losing visibility in what is going to be cached with this change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we'd actually get a clearer picture of what size ended up being persisted somewhere, as the comment above points out

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be worth adding an actual INFO or DEBUG level log here too, so we can get some hard data rather than just time series info


return $encoded;
}

Expand Down