class_docstr: Generic Adder which writes to Reverb using Reverb's `StructuredWriter`.
  
  The StructuredAdder is a thin wrapper around Reverb's `StructuredWriter` and
  its behaviour is determined by the configs to __init__. Much of the behaviour
  provided by other Adders can be replicated using `StructuredAdder` but there
  are a few noteworthy differences:
  
   * The behaviour of `StructuredAdder` can be thought of as the union of all
     its configs. This means that a single adder is capable of inserting items
     of different structures into any number of tables WITHOUT any data
     duplication. Other adders are only capable of writing items of the same
     structure into multiple tables.
   * The complete structure of the step must be known at construction time when
     using the StructuredAdder. This is not the case for other Adders as they
     allow the structure of the step to become expanded over time.
   * The `StructuredAdder` assigns all items the same priority (1.0) as it does
     not currently support custom priority computations.
   * The StructuredAdder is completely generic and thus does not perform any
     preprocessing on the data (e.g. cumulative rewards as done by the
     NStepTransitionAdder) before writing it to Reverb. The user is instead
     expected to perform preprocessing in the dataset pipeline on the learner.
class_docstr_tok: ["Generic","Adder","which","writes","to","Reverb","using","Reverb","'s","`","StructuredWriter","`",".","The","StructuredAdder","is","a","thin","wrapper","around","Reverb","'s","`","StructuredWriter","`","and","its","behaviour","is","determined","by","the","configs","to","__init__",".","Much","of","the","behaviour","provided","by","other","Adders","can","be","replicated","using","`","StructuredAdder","`","but","there","are","a","few","noteworthy","differences",":","*","The","behaviour","of","`","StructuredAdder","`","can","be","thought","of","as","the","union","of","all","its","configs",".","This","means","that","a","single","adder","is","capable","of","inserting","items","of","different","structures","into","any","number","of","tables","WITHOUT","any","data","duplication",".","Other","adders","are","only","capable","of","writing","items","of","the","same","structure","into","multiple","tables",".","*","The","complete","structure","of","the","step","must","be","known","at","construction","time","when","using","the","StructuredAdder",".","This","is","not","the","case","for","other","Adders","as","they","allow","the","structure","of","the","step","to","become","expanded","over","time",".","*","The","`","StructuredAdder","`","assigns","all","items","the","same","priority","(","1.0",")","as","it","does","not","currently","support","custom","priority","computations",".","*","The","StructuredAdder","is","completely","generic","and","thus","does","not","perform","any","preprocessing","on","the","data","(","e.g",".","cumulative","rewards","as","done","by","the","NStepTransitionAdder",")","before","writing","it","to","Reverb",".","The","user","is","instead","expected","to","perform","preprocessing","in","the","dataset","pipeline","on","the","learner","."]
docstr: Initialize a StructuredAdder instance.
  
  Args:
    client: A client to the Reverb backend.
    max_in_flight_items: The maximum number of items allowed to be "in flight"
      at the same time. See `block_until_num_items` in
      `reverb.TrajectoryWriter.flush` for more info.
    configs: Configurations defining the behaviour of the wrapped Reverb
      writer.
    step_spec: spec of the step that is going to be inserted in the Adder. It
      can be created with `create_step_spec` using the environment spec and
      and the extras spec.
docstr_tok: ["Initialize","a","StructuredAdder","instance",".","Args",":","client",":","A","client","to","the","Reverb","backend",".","max_in_flight_items",":","The","maximum","number","of","items","allowed","to","be","``","in","flight","''","at","the","same","time",".","See","`","block_until_num_items","`","in","`","reverb.TrajectoryWriter.flush","`","for","more","info",".","configs",":","Configurations","defining","the","behaviour","of","the","wrapped","Reverb","writer",".","step_spec",":","spec","of","the","step","that","is","going","to","be","inserted","in","the","Adder",".","It","can","be","created","with","`","create_step_spec","`","using","the","environment","spec","and","and","the","extras","spec","."]
code: def __init__(
      self,
      client: reverb.Client,
      max_in_flight_items: int,
      configs: Sequence[sw.Config],
      step_spec: Step,
  ):
      """Initialize a StructuredAdder instance.
  
      Args:
        client: A client to the Reverb backend.
        max_in_flight_items: The maximum number of items allowed to be "in flight"
          at the same time. See `block_until_num_items` in
          `reverb.TrajectoryWriter.flush` for more info.
        configs: Configurations defining the behaviour of the wrapped Reverb
          writer.
        step_spec: spec of the step that is going to be inserted in the Adder. It
          can be created with `create_step_spec` using the environment spec and
          and the extras spec.
      """
  
      # We validate the configs by attempting to infer the signatures of all
      # targeted tables.
      for table, table_configs in itertools.groupby(
          configs, lambda c: c.table
      ):
          try:
              sw.infer_signature(list(table_configs), step_spec)
          except ValueError as e:
              raise ValueError(
                  f"Received invalid configs for table {table}: {str(e)}"
              ) from e
  
      self._client = client
      self._configs = tuple(configs)
      self._none_step: Step = tree.map_structure(
          lambda _: None, step_spec
      )
      self._max_in_flight_items = max_in_flight_items
  
      self._writer = None
      self._writer_created_at = None
  
imports: import itertools
  import time
  from typing import Callable, List, Optional, Sequence, Sized
  from absl import logging
  from acme import specs
  from acme import types
  from acme.adders import base
  from acme.adders.reverb import base
  from acme.adders.reverb import sequence
  from acme.utils import tree_utils
  import dm_env
  import numpy
  import reverb
  from reverb import structured_writer
  import tensorflow
  import tree
label_desc: Use image node_id 1 to create a new StructuredAdder object from inherited base classes: adders_base with example: obj = StructuredAdder(client, max_in_flight_items, configs, step_spec)