When WAL consumer catchup master and change his state to streaming, not available normally complete replication by send CopyDone message until will not generate/create new WAL record. It occurs because logical decoding located in WalSndWaitForWal until will not available next WAL record, and it method receive message from consumer even reply on CopyDone with CopyDone but ignore exit from loop and we can wait many times waiting CommandStatus & ReadyForQuery packages on consumer.
Logical decoding ignore message from consumer during decoding and writing transaction in socket(WalSndWriteData). It affect long transactions with many changes. Because for example if we start decoding transaction that insert 1 million records and after consume 1% of it date we decide stop replication, it will be not available until whole million record will not send to consumer.
How exactly are you stopping the replication? If you just stop reading you'll likely to hit some problems, but what if you also close the connection? I don't think there is any other supported way to do it.
I was working last year on adding support for replication protocol to the Python driver: https://github.com/psycopg/psycopg2/pull/322 It would be nice if you could skim through this implementation, since it didn't receive a whole lot of review.