Skip to content

Instantly share code, notes, and snippets.

@aLekSer
Last active October 22, 2020 19:38
Show Gist options
  • Save aLekSer/655c43bd622199c4752bd77a6b1180d6 to your computer and use it in GitHub Desktop.
Save aLekSer/655c43bd622199c4752bd77a6b1180d6 to your computer and use it in GitHub Desktop.
Backfill flow diagram.mmd
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@aLekSer
Copy link
Author

aLekSer commented Oct 14, 2020

Screenshot 2020-10-15 at 01 34 00

@aLekSer
Copy link
Author

aLekSer commented Oct 15, 2020

Screenshot 2020-10-15 at 17 04 51

@aLekSer
Copy link
Author

aLekSer commented Oct 15, 2020

Sean's comment : A numbered list of steps would make it a little easier to understand. I still don't think the Backfill ticket should contain the list of tickets, but I might not fully understand. I think that after a Backfill ticket is created, it contains the server's IP and port (one way to populate this is to have the Backfill ticket ID in the Match that the Director receives, and the Director calls an API to populate the connection data after the Match gets a server), and the number of spots that need to be filled. The 2nd time the MMF runs, when it finds a Match that would fulfill the Backfill ticket, it will add the Backfill ticket ID to the Match. When the Match proposals are coming back to the Backend, the Backend can update the Backfill ticket and go through the assignment process for those tickets.
As a side note, the original Match that is created will also have the Backfill ticket ID in it as well. It will be added by the Backend after the Backend creates the Backfill ticket. Then the Director can pass that information on to the Game Server, so it can update the ticket if needed.

@aLekSer
Copy link
Author

aLekSer commented Oct 15, 2020

BF Ticket has properties like : remaining Number of open slots and searchFields to be used to show up in results of filter by MatchProfile pools.

@aLekSer
Copy link
Author

aLekSer commented Oct 15, 2020

M1 = {T1, BF1} M2 = {T2, BF1} - Evaluator would leave only M1 or M2.
M1 = {T1} + extensions {BF1 ID} or add to match a new field.

@scosgrave
Copy link

I added a few things to the sequence diagram. Please review.

sequenceDiagram
    participant Player
    participant GS
    participant MMF
    participant Director
    participant OpenMatchCore
    participant Backfill

    Player->>OpenMatchCore: Create Ticket T1 (skill 10)
    Director  ->> + OpenMatchCore: FetchMatches
    OpenMatchCore->>+MMF: Run
    MMF->>+OpenMatchCore: Query Tickets
    OpenMatchCore->>-MMF: Return ticket T1: Match is not full
    MMF->>-OpenMatchCore: Return Match with T1<br/> Add BF Ticket creation info to Match
    OpenMatchCore->>+Backfill: Create BF-Ticket<br/> Put average skill (10) as searchfield (optional)
    Note right of Backfill: BF-Ticket contains: <br/>-Current/Desired number of players<br/>-SearchFields 
    Backfill->>-OpenMatchCore: BF-Ticket ID: BF1
    Note left of OpenMatchCore: Update Match object new members:<br/>BackfillTicketID: BF1<br/>Allocated: false
    OpenMatchCore  ->> - Director: Match (partially filled)
    Note right of Director: if !Match.Allocated, Director allocates
    Director ->> GS: Allocate GS with BF-Ticket ID
    Note right of Director: Add new member to AssignmentGroup:<br/>BackfillTicketID: BF1
    Director ->> OpenMatchCore: Assign(assignments: [{ticket_ids:[T1], assignment:"ip:port", backfillID: BF1}]) 
    OpenMatchCore->>+Backfill: Get(bfTicketID: string)
    Backfill->>-OpenMatchCore: Ticket BF1
    Note right of OpenMatchCore: OpenMatchCore will see no IP:Port on BF1, so will add it
    OpenMatchCore->>Backfill: Assign(bfTicketID: string, assignment: string)
    opt 
        GS -x OpenMatchCore: Remove BF Ticket
    end
    Player ->> OpenMatchCore: Fetch ConnInfo
    Player ->> GS: Connect using ConnInfo
Note over Player: Next Iteration (Player2)
    Player->>OpenMatchCore: Create Ticket T2 (skill 18)
    Director  ->>  +OpenMatchCore: Fetch matches
    OpenMatchCore->>+MMF: Run 
    MMF->>+OpenMatchCore: Get Tickets with Skill < 20
    OpenMatchCore->>-MMF: Retrieve two tickets (BF1 and new T2)
    Note over MMF: Received 1 BF-Ticket and 1 regular T2
    MMF->> -OpenMatchCore: Match(tickets: [T2], backfillTicketID: BF1, backfillCreateParams: {}, allocated: True)
    OpenMatchCore  ->> - Director: Match(tickets: [T2], backfillTicketID: BF1, backfillCreateParams: {}, allocated: True)
    Director -x GS: Notify GS about new match & players using current BF1 id
    Director ->> OpenMatchCore: Assign(assignments: [{ticket_ids:[T2], assignment:"ip:port", backfillID: BF1}]) 
    OpenMatchCore->>+Backfill: Get(bfTicketID: string)
    Backfill->>-OpenMatchCore: Ticket BF1
    Note right of OpenMatchCore: OpenMatchCore will see IP:Port on BF1, so will just change open slot count<br/>and search fields
    OpenMatchCore->>Backfill: Update(bfTicket: BFTicket)
    Player ->> OpenMatchCore: Fetch ConnInfo
    Player ->> GS: Connect using ConnInfo
opt
    GS ->> OpenMatchCore: Update BF1, set available slots to N (N - number of players)
end
opt
    GS ->> OpenMatchCore: Remove BF-Ticket before shutdown
end
opt
    GS ->> OpenMatchCore: Create BF-Ticket again when GS is waiting for new players
end

@scosgrave
Copy link

backfill_sequence_scosgrave

@aLekSer
Copy link
Author

aLekSer commented Oct 16, 2020

Thanks for an updated, applied your version to this gist as revision 5.
As I see here you introduced a change to Assign operation which now will holds a new BackfillID argument, in that way we can do both operations in one place.

@aLekSer
Copy link
Author

aLekSer commented Oct 19, 2020

A new version proposed by @scosgrave , revision 6
backfill_delayed_async_assignment

@scosgrave
Copy link

scosgrave commented Oct 19, 2020

This revision tries to solve the problem of having a second or third round of match making complete prior to the first one getting an allocated game server. This situation might happen if game server allocation happens asynchronously to match making.

One potential issue with this flow is that it breaks one of the properties of the Director. Usually the Director knows which tickets have been assigned because it is the one calling AssignTickets, but in this flow, if a 2nd match making round completed before the allocation happened, then the Backfill service calls AssignTickets on the tickets that are in the unassignedTicket array. The Director has no idea that those tickets have been assigned. It could find out that they were assigned if it called WatchAssignments on tickets that were in the unassignedTickets array, but that would require the Director to create a go-routine per unassignedTicket, which doesn't scale well. It would be better if the Director's domain name, or IP, and port were sent in with the FetchMatches request, and saved with the Backfill ticket. Then the Backfill service could call an API on each Director associated with the Backfill ticket, to notify the Director that these tickets were assigned.

A second option could be the create a new API on the FrontEnd called WatchManyAssignments which could get the assignments for many tickets with one request. This might cut down on the number of go-routines watching assignments from the Director, but again, it is also possible it could degenerate into a single go-routine per ticket.

I don't think trying to watch the tickets from the Director is going to work. I think the most efficient approach is going to be having the Backfill or OpenMatch Backend notify the Director that a ticket, or tickets, have been assigned. Or, we need to come up with a different flow.

@scosgrave
Copy link

One more note about the last sequence diagram that was posted.
When Matches are returned to the Director, we should always populate the new tickets that were added to the Backfill in the tickets slice. The reason for this is the Director can't tell which tickets in the unassignedTickets array were most recently added. If we put the newly added tickets in the tickets member, then the Director can tell the newly added tickets from the existing ones in the unassignedTickets slice on the Backfill ticket.
Based on this idea, here are some example responses to the Director, and their meaning:

Tickets T1, and T2 were matched together, but the match is not full, so a Backfill Ticket was created. This is the first time any tickets have been associated with this Match, so needsAssignment is True, and the Director should allocate a game server for the Match:
Match(tickets: [T1, T2], backfillTicket{ID: BF1, needsAssignment: True, unassignedTickets[]})

Ticket T3 and T4 were added to the Backfill Ticket, but the game server allocation for the match hasn't completed yet, so they were added to the unassignedTickets slice:
Match(tickets: [T3, T4], backfillTicket{ID: BF1, needsAssignment: False, unassignedTickets[T3, T4]})

Tickets T5 and T6 matched into this Backfill Ticket, but the game server allocation for the match hasn't completed yet, so they were added to the unassignedTickets slice:
Match(tickets: [T5, T6], backfillTicket{ID: BF1, needsAssignment: False, unassignedTickets[T3, T4, T5, T6]})

Tickets T7 and T8 matched into this Backfill Ticket. The game server allocation has already happened, so the Director should be able to get the connection info from the Backfill Ticket, and call AssignTickets right away without doing any game server allocation:
Match(tickets: [T7, T8], backfillTicket{ID: BF1, needsAssignment: False, unassignedTickets[]})

@aLekSer
Copy link
Author

aLekSer commented Oct 19, 2020

Made a new diagram (rev 7), updating current gist.
The idea here is that Director always would perform assignments.
It can skip the backfill ticket for some reason, so it can have more options how to treat unassigned_tickets. He can use some of them for instance, and UpdateBFTicket with the rest, so later on for example on delete all UnassignedTickets could be returned to the pool of tickets. This way we don't have the only one implementation contained inside OM Core.
Updated Diagram with Director only assignments

@aLekSer
Copy link
Author

aLekSer commented Oct 22, 2020

An idea is to add one more bool field to the Match - allocate_gameserver, it should be set to false every time but only in the first match output to the director the Match would contain allocate_gameserver = true.
Backfill Match allocate_gameserver field

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment