Beispiel #1
0
// Load will load all related entities for the supplied struct, or slice, as
// long as the struct type and callback handlers have been registered.
// Note: A collection is expected to be of the same type, mixed type slices will
// have incorrect data, or may even panic.
func Load(context *ctx.Context, data interface{}, required []string) (map[string]map[string]interface{}, error) {
	if required == nil {
		context.Lock()
		defer context.Unlock()
		return preloadedEntities(context), nil
	}

	ids, err := idsFromData(data, required...)
	if err != nil {
		return nil, err
	}

	// At this point the ids map is ready for hydration.
	return hydrateEntitiesFromMap(context, ids)
}
Beispiel #2
0
// hydrateEntitiesFromMap will take an entity ids map, and return the results
// for each of the entity types and their ids. This requires a handler for the
// entity types to have been registered previously.
func hydrateEntitiesFromMap(context *ctx.Context, ids map[string]map[string]bool) (map[string]map[string]interface{}, error) {
	context.Lock()
	entities := preloadedEntities(context)
	context.Unlock()
	if len(ids) == 0 {
		return entities, nil
	}

	resultChan := make(chan entityCollectionResult)
	for name, idMap := range ids {
		// Turn the map of ids into a slice.
		idSlice := make([]string, len(idMap))
		i := 0
		for id := range idMap {
			idSlice[i] = id
			i++
		}
		// Go get the entity collection
		go singleEntityCollection(context, resultChan, name, idSlice)
	}

	var firstErr error
	// Loops over the ids again, for the correct count.
	for _ = range ids {
		// Retrieve a result off the result chan.
		result := <-resultChan
		// An error should be assigned to the firstErr is it's empty.
		if result.err != nil {
			if firstErr == nil {
				firstErr = result.err
			}
			continue
		}
		// Results get assigned back to the entities being returned.
		if existingEntities, ok := entities[result.name]; ok {
			for key, value := range result.results {
				existingEntities[key] = value
			}
			entities[result.name] = existingEntities
		} else {
			entities[result.name] = result.results
		}
	}
	return entities, firstErr
}