Split actions into chunks by number or size, serialize them into strings in
    the process.

def _chunk_actions(actions, chunk_size, max_chunk_bytes, serializer):
    """
    Split actions into chunks by number or size, serialize them into strings in
    the process.
    """
    bulk_actions, bulk_data = [], []
    size, action_count = 0, 0
    for action, data in actions:
        raw_data, raw_action = data, action
        action = serializer.dumps(action)
        # +1 to account for the trailing new line character
        cur_size = len(action.encode("utf-8")) + 1

        if data is not None:
            data = serializer.dumps(data)
            cur_size += len(data.encode("utf-8")) + 1

        # full chunk, send it and start a new one
        if bulk_actions and (
            size + cur_size > max_chunk_bytes or action_count == chunk_size
        ):
            yield bulk_data, bulk_actions
            bulk_actions, bulk_data = [], []
            size, action_count = 0, 0

        bulk_actions.append(action)
        if data is not None:
            bulk_actions.append(data)
            bulk_data.append((raw_action, raw_data))
        else:
            bulk_data.append((raw_action,))

        size += cur_size
        action_count += 1

    if bulk_actions:
        yield bulk_data, bulk_actions