Beispiel #1
0
func main() {
	fmt.Println("* Booting cities service...")

	fmt.Println("* Loading configuration...")
	options := config.Load("config.json")

	fmt.Println("* Connecting to the database...")
	db, err := bolt.Open("cities.db", 0600, nil)
	if err != nil {
		panic(fmt.Sprintf("[DB] Couldn't connect to the db: %v", err))
	}

	c := cache.New()
	parsingDone := make(chan bool, 1)

	if ds.GetAppStatus(db).IsIndexed() {
		fmt.Println("[PARSER] Skipping, already done")
		parsingDone <- true
	} else {
		go parser.Scan(
			db, parsingDone, options.Locales, options.MinPopulation,
			options.CountriesFile, options.CitiesFile,
			options.AlternateNamesFile,
		)
	}

	<-parsingDone
	fmt.Println("[CACHE] Warming up...")
	warmUpSearchCache(db, c, options.Locales, 5)
	fmt.Println("[CACHE] Warming up done")

	fmt.Printf("* Listening on port %s\n\n", options.Port)
	log.Fatal(Server(db, options, c).ListenAndServe())
}
Beispiel #2
0
func TestCities(t *testing.T) {
	Convey("Append city", t, func() {
		db := h.CreateDB(t)
		CreateCountriesBucket(db)

		h.PutToBucket(
			t, db, CountriesBucketName, "1",
			"US\tUnited States\ten|United States;ru|Соединенные Штаты",
		)

		cities := Cities{
			Cities: []*City{
				&City{Name: "Venice"}, &City{Name: "Moscow"},
			},
		}

		Convey("When no city with the same name is in the collection", func() {
			city := City{Name: "London"}
			actual := appendCity(db, cities.Cities, &city, "en")

			Convey("Adds the city to the array", func() {
				So(len(actual), ShouldEqual, 3)
			})

			Convey("Leaves the city name unchanged", func() {
				So(actual[2].Name, ShouldEqual, city.Name)
			})
		})

		Convey("When city with the same name is in the collection", func() {
			Convey("When the country exists for the given code", func() {
				city := City{Name: "Venice", CountryCode: "US"}

				Convey("Default locale", func() {
					actual := appendCity(db, cities.Cities, &city, "en")

					Convey("Adds the city to the array", func() {
						So(len(actual), ShouldEqual, 3)
					})

					Convey("Adds the country name to the city name", func() {
						So(actual[2].Name, ShouldEqual, "Venice, United States")
					})
				})

				Convey("Some other locale", func() {
					actual := appendCity(db, cities.Cities, &city, "ru")

					Convey("Adds the city to the array", func() {
						So(len(actual), ShouldEqual, 3)
					})

					Convey("Adds the country name to the city name", func() {
						So(actual[2].Name, ShouldEqual, "Venice, Соединенные Штаты")
					})
				})
			})

			Convey("When no country exists for the given code", func() {
				city := City{Name: "Moscow", CountryCode: "MO"}
				actual := appendCity(db, cities.Cities, &city, "en")

				Convey("Doesn't adds the city to the array", func() {
					So(len(actual), ShouldEqual, 2)
				})
			})
		})
	})

	Convey("Search cites", t, func() {
		db := h.CreateDB(t)
		CreateCitiesBucket(db)
		CreateCityNamesBucket(db)

		cityNames := CityNames{
			&CityName{
				Key: "montreal", Name: "Montréal", CityId: 1,
				Locale: "fr", Population: 1600000,
			},
			&CityName{
				Key: "moscow", Name: "Moskau", CityId: 2,
				Locale: "de", Population: 12000000,
			},
		}
		for _, cn := range cityNames {
			h.PutToBucket(t, db, CityNamesBucketName, cn.Key, cn.toString())
		}

		cities := []*City{
			&City{ID: 1, Name: "Montreal"},
			&City{ID: 2, Name: "Moscow"},
		}
		for _, city := range cities {
			h.PutToBucket(
				t, db, CitiesBucketName, strconv.Itoa(city.ID), city.toString(),
			)
		}

		locales := []string{"ru", "en", "de"}

		Convey("Non cached search", func() {
			result, err := SearchCities(db, locales, "Mo", 5)

			Convey("Finds matching cities", func() {
				So(len(result.Cities), ShouldEqual, 2)
				So(result.Cities[0].ID, ShouldEqual, cities[1].ID)
				So(result.Cities[1].ID, ShouldEqual, cities[0].ID)
			})

			Convey("Sets the city names from the mathing cityname", func() {
				So(result.Cities[0].Name, ShouldEqual, cityNames[1].Name)
				So(result.Cities[1].Name, ShouldEqual, cityNames[0].Name)
			})

			Convey("Returns no error", func() {
				So(err, ShouldBeNil)
			})
		})

		Convey("Cached search", func() {
			c := cache.New()

			Convey("For short queries", func() {
				results, expectedErr := SearchCities(db, locales, "Mo", 5)
				cacheMissResults, actualErr := CachedCitiesSearch(db, c, locales, "Mo", 5)
				cacheHitResults, _ := CachedCitiesSearch(db, c, locales, "Mo", 5)

				Convey("Returns results from search if cache miss", func() {
					So(cacheMissResults, ShouldResemble, results)
					So(actualErr, ShouldEqual, expectedErr)
				})

				Convey("Returns results from cache if cache hit", func() {
					So(cacheHitResults, ShouldResemble, cacheMissResults)
				})
			})

			Convey("For longer queries", func() {
				expected, expectedErr := SearchCities(db, locales, "Moscow", 5)
				actual, actualErr := CachedCitiesSearch(db, c, locales, "Moscow", 5)

				Convey("Returns results from search if cache miss", func() {
					So(actual, ShouldResemble, expected)
					So(actualErr, ShouldEqual, expectedErr)
				})
			})
		})
	})
}