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)
        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
        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
