Skip to content

Commit

Permalink
Merge pull request #98 from BuddyGG/development
Browse files Browse the repository at this point in the history
 Release 1.2.0
  • Loading branch information
ecly committed Apr 4, 2018
2 parents 2122ea5 + 7e378df commit 1d06356
Show file tree
Hide file tree
Showing 86 changed files with 918 additions and 349 deletions.
13 changes: 6 additions & 7 deletions .deliver/config
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
APP="buddy_matching"
APP="buddy"

BUILD_HOST="buddy.gg"
BUILD_USER="worker"
Expand All @@ -7,17 +7,16 @@ BUILD_AT="/home/worker/app_build"
PRODUCTION_HOSTS="buddy.gg"
PRODUCTION_USER="worker"
DELIVER_TO="/home/worker/app_release"
# We manually increment versions in mix.exs
# using semantic versioning instead.
# AUTO_VERSION=revision

pre_erlang_get_and_update_deps() {
# copy it on the build host to the build directory when building
local _secret_config_file_on_build_host="~/secret/buddy_matching.conf"
local _secret_config_buddy_matching_web="~/secret/buddy_matching_web.conf"
local _secret_config_riot_api="~/secret/riot_api.conf"
if [ "$TARGET_MIX_ENV" = "prod" ]; then
status "Copying '$_secret_config_file_on_build_host' file to build dir"
status "Copying secret files to build dir"
__sync_remote " # execute on build host
cp $_secret_config_file_on_build_host $BUILD_AT/config/buddy_matching.conf
cp $_secret_config_buddy_matching_web $BUILD_AT/apps/buddy_matching_web/config/buddy_matching_web.conf
cp $_secret_config_riot_api $BUILD_AT/apps/riot_api/config/riot_api.conf
"
fi
}
4 changes: 2 additions & 2 deletions .formatter.exs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
inputs: ["mix.exs", "apps/*/{config,lib,test}/**/*.{ex,exs}"]
]
36 changes: 21 additions & 15 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
# App artifacts
/_build
/db
/deps
/*.ez
.elixir_ls/
# Generated on crash by the VM
# The directory Mix will write compiled artifacts to.
/_build/

# If you run "mix test --cover", coverage assets end up here.
/cover/

# The directory Mix downloads your dependencies sources to.
/deps/

# Where 3rd-party dependencies like ExDoc output generated docs.
/doc/

# Ignore .fetch files in case you like to edit your project deps locally.
/.fetch

# If the VM crashes, it generates a dump, let's ignore it too.
erl_crash.dump
.deliver/releases/

# Files matching config/*.secret.exs pattern contain sensitive
# data and you should not commit them into version control.
#
# Alternatively, you may comment the line below and commit the
# secrets files as long as you replace their contents by environment
# variables.
/config/*.secret.exs
# Also ignore archive artifacts (built via "mix archive.build").
*.ez

# Ignore all releases that we've built
.deliver/releases/
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
language: elixir

elixir:
- 1.5.1
- 1.6

otp_release:
- 20.1
Expand All @@ -17,4 +17,4 @@ notifications:
sudo: false

script:
- mix test
- mix coveralls.travis --umbrella
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1 +1 @@
web: MIX_ENV=prod mix phoenix.server
web: MIX_ENV=prod mix phx.server
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# Backend service for buddy.gg
[![Build Status](https://travis-ci.org/BuddyGG/buddy_matching.png)](https://travis-ci.org/BuddyGG/buddy_matching)
[![Coverage Status](https://coveralls.io/repos/github/BuddyGG/buddy_matching/badge.svg?branch=add-coveralls)](https://coveralls.io/github/BuddyGG/buddy_matching?branch=add-coveralls)

Somewhat generic player matching service built with phoenix, utilizing genservers and sockets to avoid having an underlying database.
Currently build only support matching players from League of Legends, but can quite easily be expanded to other games
Somewhat Generic player matching service built with Phoenix, utilizing GenServers and sockets to avoid having an underlying database.
Currently built only to support matching players from League of Legends, but can ideally be easily extended to support multiple games.

## Run local
To start the server:
Expand Down
3 changes: 3 additions & 0 deletions apps/buddy_matching/.formatter.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
18 changes: 18 additions & 0 deletions apps/buddy_matching/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# App artifacts
/_build
/db
/deps
/*.ez
.elixir_ls/
# Generated on crash by the VM
erl_crash.dump
.deliver/releases/
# Ignore code coverage results
/cover

# Files matching config/*.secret.exs pattern contain sensitive
# data and you should not commit them into version control.
#
# Alternatively, you may comment the line below and commit the
# secrets files as long as you replace their contents by environment
# variables.
15 changes: 15 additions & 0 deletions apps/buddy_matching/config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# This file is responsible for configuring your application
# and its dependencies with the aid of the Mix.Config module.
#
# This configuration file is loaded before any dependency and
# is restricted to this project.
use Mix.Config

# Configures Elixir's Logger
config :logger, :console,
format: "$time $metadata[$level] $message\n",
metadata: [:request_id]

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
4 changes: 4 additions & 0 deletions apps/buddy_matching/config/dev.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use Mix.Config

# Print only warnings and errors during test
config :logger, level: :debug
3 changes: 3 additions & 0 deletions apps/buddy_matching/config/prod.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use Mix.Config

config :logger, level: :info
4 changes: 4 additions & 0 deletions apps/buddy_matching/config/test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
use Mix.Config

# Print only warnings and errors during test
config :logger, level: :warn
27 changes: 27 additions & 0 deletions apps/buddy_matching/lib/application.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule BuddyMatching.Application do
@moduledoc """
Application configuration. The PlayerServer.Supervisor is started from here.
"""

use Application

# See https://hexdocs.pm/elixir/Application.html
# for more information on OTP Applications
def start(_type, _args) do
import Supervisor.Spec

# Define workers and child supervisors to be supervised
children = [
# Start the endpoint when the application starts
supervisor(BuddyMatching.PlayerServer.Supervisor, [])
# Start your own worker by calling:
# BuddyMatching.Worker.start_link(arg1, arg2, arg3)
# worker(BuddyMatching.Worker, [arg1, arg2, arg3]),
]

# See https://hexdocs.pm/elixir/Supervisor.html
# for other strategies and supported options
opts = [strategy: :one_for_one, name: BuddyMatching.Supervisor]
Supervisor.start_link(children, opts)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,7 @@ defmodule BuddyMatching.PlayerServer do
"""
use GenServer
require Logger
alias BuddyMatching.Players
alias BuddyMatching.Players.Player
alias BuddyMatchingWeb.Endpoint
alias BuddyMatchingWeb.PlayersChannel
alias Phoenix.Socket.Broadcast

@doc """
Starts the PlayerServer.
Expand Down Expand Up @@ -56,63 +52,42 @@ defmodule BuddyMatching.PlayerServer do
if Map.has_key?(list, player.name) do
{:reply, :error, list}
else
:ok = Endpoint.subscribe("players:" <> player.id, [])
{:reply, :ok, Map.put_new(list, player.name, player)}
end
end

# Handle casts with remove - asynchronous
# Remove a player from the state
# Returns {:noreply, <state>}
def handle_cast({:remove, player}, list) do
{:noreply, Map.delete(list, player.name)}
# Handle call with remove - synchronous
# Remove a player from the state given their name
#
# If Player was in state and was removed, returns
# Returns {:reply, {:ok, player}, <updated_state>}
#
# If Player did not exist in state, returns:
# Returns {:reply, :error, <state>}
def handle_call({:remove, key}, _from, state) do
case Map.fetch(state, key) do
{:ok, player} -> {:reply, {:ok, player}, Map.delete(state, key)}
_ -> {:reply, :error, state}
end
end

# Handle casts with update - asynchronous
# Handle call with update - synchronous
# Updates a player from the state, hence expects at least
# the key, to match a player in the state. - If the key does not exist,
# nothing is done.
# Returns {:noreply, <state>}
def handle_cast({:update, player}, state) do
#
# If Player was in state returns:
# Returns {:reply, :ok, <updated_state>}
#
# Otherwise if Player wasn't in state, returns:
# Returns {:reply, :error, <state>}
def handle_call({:update, player}, _from, state) do
case Map.fetch(state, player.name) do
{:ok, _} -> {:noreply, Map.put(state, player.name, player)}
_ -> {:noreply, state}
{:ok, _} -> {:reply, :ok, Map.put(state, player.name, player)}
_ -> {:reply, :error, state}
end
end

# When we get a 'presence_diff' with no leaves, we do nothing.
def handle_info(%Broadcast{event: "presence_diff", payload: %{leaves: %{} = leaves}}, state)
when leaves == %{} do
{:noreply, state}
end

# When a player leaves the channel, we unsubscribe to his topic,
# remove him from the state. In a separate process alert all the matches
# he may have had, that he has left.
def handle_info(%Broadcast{event: "presence_diff", payload: %{leaves: leaves}}, state) do
[name | _] =
leaves
|> Map.values()
|> Enum.map(fn %{metas: [%{name: name}]} -> name end)

# local function for broadcasting player leaves
Task.start(fn ->
[topic | _] = Map.keys(leaves)
Endpoint.unsubscribe("players:" <> topic)

if Map.has_key?(state, name) do
player = state[name]
Logger.debug(fn -> "Player #{inspect(player)} has left" end)

player
|> Players.get_matches(Map.values(state))
|> PlayersChannel.broadcast_unmatches(player)
end
end)

{:noreply, Map.delete(state, name)}
end

# We ignore all other messages
def handle_info(_, state) do
{:noreply, state}
Expand Down Expand Up @@ -140,7 +115,7 @@ defmodule BuddyMatching.PlayerServer do
Method will run synchronously.
## Examples
iex> p1 = %Player{}
iex> p1 = %Player{name: "Lethly"}
iex> BuddyMatching.PlayerServer.add(p1)
:ok
iex> BuddyMatching.PlayerServer.add(p1)
Expand All @@ -152,29 +127,43 @@ defmodule BuddyMatching.PlayerServer do

@doc """
Deletes the given player from the specified server
Always returns :ok if server exists.
Method will run asynchronously.
Returns :ok if player was in state, otherwise :error.
Method will run synchronously.
## Examples
iex> BuddyMatching.PlayerServer.remove(%Player{name: "Lethly"})
:ok
"""
def remove(pid, %Player{name: name}) do
GenServer.call(pid, {:remove, name})
end

@doc """
Deletes the a player from the specified server, given their name.
Returns :ok if player was in state, otherwise :error.
Method will run synchronously.
## Examples
iex> BuddyMatching.PlayerServer.remove(%Player{})
iex> BuddyMatching.PlayerServer.remove("Lethly")
:ok
"""
def remove(pid, %Player{} = player) do
GenServer.cast(pid, {:remove, player})
def remove(pid, name) do
GenServer.call(pid, {:remove, name})
end

@doc """
Updates the given player from the specified server
if he exists in the server's state. That is, if his key
currently exists in the state.
Always returns :ok if server exists.
Method will run asynchronously.
Returns :ok if player was in state and is updated,
otherwise returns :error.
Method will run synchronously.
## Examples
iex> BuddyMatching.PlayerServer.update(%Player{name = "Lethly"})
:ok
"""
def update(pid, %Player{} = player) do
GenServer.cast(pid, {:update, player})
GenServer.call(pid, {:update, player})
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ defmodule BuddyMatching.PlayerServer.RegionMapper do
|> PlayerServer.remove(player)
end

@doc """
Removes a player given their region and their name.
## Examples
iex> player = %{id: 1, name: "Lethly", region: :some_region}
iex> BuddyMatching.RegionMapper.add_player(player)
:ok
iex> BuddyMatching.RegionMapper.remove_player("Lethly", :some_region)
:ok
"""
def remove_player(name, region) do
region
|> :global.whereis_name()
|> PlayerServer.remove(name)
end

@doc """
Updates the given player from its region's PlayerServer
This will have no effect if the player isn't already in the PlayerServer.
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 1d06356

Please sign in to comment.