I'm trying to pre-fetch an object graph of files in a Github repository using Octokit which depends on Reactive Cococa. I'm running into an issue creating a signal that will drill down, recursively, until there are no more directories to be fetched. Here is an example directory graph of a repository of mine (note: files have been omitted to keep the graph simple and clean).
- (RACSignal *)fetchContentTreeForRepository:(OCTRepository *)repository {
return [[self fetchContent:Nil forRepository:repository parentContent:nil] doCompleted:^{
// fetching tree finished, persist in database
}];
}
- (RACSignal *)fetchContent:(OCTContent *)content forRepository:(OCTRepository *)repository parentContent:(OCTContent *)parentContent {
return [[[[self.client fetchContents:content forRepository:repository] collect] deliverOn:RACScheduler.mainThreadScheduler]
flattenMap:^RACSignal *(NSArray *fetchedContents) {
// set the contents that were fetched
id<OCTContentStoreProtocol>store = content ?: repository;
store.contents = fetchedContents;
// only search for contents of type "dir" (directory)
NSArray *directories = [fetchedContents filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"contentType = \"dir\""]];
NSMutableArray *signals;
for (OCTContent *fetchedDir in directories) {
[signals addObject:[self fetchContent:fetchedDir forRepository:repository parentContent:content]];
}
return [RACSignal merge:signals];
}];
}
As a note: -fetchContents:forRepository:
builds a request path and returns a RACSignal
that enqueues an HTTP request operation (it tries to follow the semantics OctoKit does).
The problem I'm running into currently is that this setup only executes the fetch for the contents of the repository (i.e. the top-level object in the graph). -flattenMap:
is called, the array of signals is appropriately created, and the -merge:
is returned. The intention is to create a recursive chain that ends when there are no more directory type children (should probably add a -filter:
to check for that).
The intension is to fetch the entire graph of files for a Github repository and be notified when the operation is finished. Here's an example of how I'd like to handle calling this:
[[[GHDataStore sharedStore] fetchContentTreeForRepository:self.repository]
subscribeNext:^(NSArray *contents) {
// this would be called each time a new set of contents is received
NSLog(@"received %i contents",[contents count]);
}
error:^(NSError *error) {
NSLog(@"error fetching: %@",error.localizedDescription);
}
completed:^{
// this would be called when mapping the graph is finished
NSLog(@"finished fetching contents");
}];
Any idea why it only executes the top level? I would have thought that calling -subscribeNext:
on -fetchContentTreeForRepository:
would be what executes the returned signal for -flattenMap:
, but it seems I'm misunderstanding something. This assumption comes from the chaining example in the Reactive Cocoa readme.
edit: I am dumb.
The issue is that you never initialize your NSMutableArray
of signals:
NSMutableArray *signals;
for (OCTContent *fetchedDir in directories) {
[signals addObject:[self fetchContent:fetchedDir forRepository:repository parentContent:content]];
}
return [RACSignal merge:signals];
Change that first line to NSMutableArray *signals = [NSMutableArray new]
and it seems to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With