Q:

How to specify retention time for stream-stream joins? 

I'd like to understand which is the retention time for structured streaming in spark.  
I've different spark structured streaming streams: 

Stream A: it arrives every 10 seconds, starting from time t0;
Stream B: it arrives every 10 seconds, starting from time t0;
Stream C: it arrives every 10 seconds, starting from time t1;

I need to apply a machine learning model using a pandas udf on these data.  Stream A and stream B go indipendentely.  
Data from stream C need to be joined with Stream A and B, before being processed. 
My question is: how I ensure that data that are processed in Stream A and Stream B are not thrown away?  Just using watermark is sufficient to achieve this?  

A:

how I ensure that data that are processed in Stream A and Stream B are not thrown away?  Just using watermark is sufficient to achieve this? 

That's right.  The state of a stream-stream join is kept forever so the first question of yours is handled out of the box while the second requires a watermark and "additional join conditions". 
Quoting Inner Joins with optional Watermarking:

Inner joins on any kind of columns along with any kind of join conditions are supported.  However, as the stream runs, the size of streaming state will keep growing indefinitely as all past input must be saved as any new input can match with any input from the past.  To avoid unbounded state, you have to define additional join conditions such that indefinitely old inputs cannot match with future inputs and therefore can be cleared from the state. 

Define watermark delays on both inputs such that the engine knows how delayed the input can be (similar to streaming aggregations)

Define a constraint on event-time across the two inputs such that the engine can figure out when old rows of one input is not going to be required (i.e. will not satisfy the time constraint) for matches with the other input.