How to merge multiple AsyncStream, not just two or three?

I am using DispatchSourceFileSystemObject to listen to file changes; I created a small function that takes a URL and listen to the event changed in the file.

private struct MonitoredFile {
	let url: URL
	let fileHandle: FileHandle
	let source: DispatchSourceFileSystemObject

	init(url: URL) throws {
		self.url = url

		fileHandle = try FileHandle(forReadingFrom: url)
		source = DispatchSource.makeFileSystemObjectSource(
			fileDescriptor: fileHandle.fileDescriptor,
			eventMask: .all,
			queue: DispatchQueue.main
		)
	}
}

	public func startMonitoring(url: URL) -> AsyncThrowingStream<DispatchSource.FileSystemEvent, Error> {
		AsyncThrowingStream { continuation in
			do {
				let monitoredFile = try MonitoredFile(url: url)

				monitoredFile.source.setEventHandler {
					continuation.yield(monitoredFile.source.data)
				}
				monitoredFile.source.setCancelHandler {
					do {
						try monitoredFile.fileHandle.close()
					} catch {
						continuation.finish(throwing: FileMonitorError.closingFileHandleError(url))
					}
				}

				try monitoredFile.fileHandle.seekToEnd()
				monitoredFile.source.resume()
			} catch {
				continuation.finish(throwing: FileMonitorError.failedMonitoringFile(url))
			}
		}
	}

Later, I noticed that Listening to multiple files in the same directory would be better than just one.
I saw that swift-async-algorithms has a merge function that merges two or three AsyncStream.

My question is, how can I merge multiple streams and not limit them to a specific number?

1 Like

Without having looked into it, this is probably something that variadic generics would make more feasible

There are two different and not yet implemented algorithms:

  1. A variadic generic version of merge as @David_Smith pointed out. Variadics are still being work on and we are planning to try to implement a variadic merge once the feature stabilized more.
  2. A merge that takes an array of async sequences. This is probably what you want but we need AsyncSequence to adopt primary associated types otherwise you are able to just merge an array of same type async sequences.

We have an issue tracking the latter `Sequence`-based implementation of combining algorithms in addition to variadic ones · Issue #226 · apple/swift-async-algorithms · GitHub

1 Like

Also there is a strategy in the interim; given 4 async sequences you can merge(merge(merge(a, b), c), d) etc. It wouldn't be as efficient as the variadic version would be but would get the job done.

note: the type signature for that could get out of hand really quickly...

2 Likes