Ignore:
Timestamp:
11/28/19 14:41:10 (5 years ago)
Author:
bart
Message:

Release 1.1.0

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/main/java/geniusweb/partiesserver/websocket/PartySocket.java

    r4 r8  
    55import java.net.URI;
    66import java.util.Date;
     7import java.util.List;
     8import java.util.concurrent.CopyOnWriteArrayList;
    79import java.util.logging.Level;
    810
     
    2325import geniusweb.actions.Action;
    2426import geniusweb.actions.PartyId;
    25 import geniusweb.connection.DefaultConnection;
     27import geniusweb.connection.ConnectionEnd;
    2628import geniusweb.partiesserver.repository.RunningPartiesRepo;
    2729import geniusweb.partiesserver.repository.RunningParty;
    2830import geniusweb.party.Party;
    29 import geniusweb.party.inform.Finished;
    3031import geniusweb.party.inform.Inform;
    3132import geniusweb.party.inform.Settings;
     
    4142 */
    4243@ServerEndpoint("/party/{party}")
    43 public class PartySocket extends DefaultConnection<Inform, Action> {
     44public class PartySocket implements ConnectionEnd<Inform, Action> {
    4445        private final static ObjectMapper jackson = new ObjectMapper();
    4546        private final Reporter log;
    4647        private final RunningPartiesRepo runningparties;
     48        private final List<Listener<Inform>> listeners = new CopyOnWriteArrayList<Listener<Inform>>();
    4749
    4850        // should all be final, except that we can only set them when start is
     
    8688                                                runningparties.removeListener(this);
    8789                                                session.close(new CloseReason(CloseCodes.GOING_AWAY,
    88                                                                 "party died"));
     90                                                                "detected that party vanished"));
    8991                                        } catch (IOException e) {
    9092                                                log.log(Level.WARNING,
     
    131133                                party.inform(info);
    132134                        } catch (Throwable e) {
    133                                 // simple sandbox
    134                                 log.log(Level.WARNING, "Party failed on inform:", e);
     135                                log.log(Level.WARNING, "Party failed on inform.", e);
     136                                // we don't use jackson.writeValueAsString(e) here because
     137                                // CloseReason has 123 char limit.
     138                                // The error will be too large to fit and will be truncated
     139                                // therefore we send a plain string and hope that enough
     140                                // will arrive at the other side (the protocol)
     141                                session.close(new CloseReason(
     142                                                CloseReason.CloseCodes.CLOSED_ABNORMALLY,
     143                                                "party threw exception: " + collectReasons(e)));
    135144                        }
    136                 } // else dead but that's handled in the listener above
     145                } // else party is dead but that's handled in the listener above
     146        }
     147
     148        /**
     149         *
     150         * @param e an exception
     151         * @return collect all reasons and sub-reasons
     152         */
     153        private String collectReasons(Throwable e) {
     154                String reason = "";
     155                do {
     156                        reason = reason + " : " + e.getClass().getSimpleName() + ":"
     157                                        + e.getMessage();
     158                        e = e.getCause();
     159                } while (e != null);
     160                return reason;
    137161        }
    138162
     
    145169         */
    146170        private void sniff(Inform info, RunningParty party) throws IOException {
    147                 if (info instanceof Finished) {
    148                         session.close(new CloseReason(CloseCodes.GOING_AWAY,
    149                                         "session reached agreement"));
    150                 } else if (info instanceof Settings) {
     171                // do NOT sniff Finished messages and close sockets. Parties and their
     172                // sockets need to stay running till all messages are handled
     173                if (info instanceof Settings) {
    151174                        Date end = ((Settings) info).getProgress().getTerminationTime();
    152175                        runningparties.replace(party.withEndTime(end));
     
    209232        }
    210233
     234        @Override
     235        public void addListener(Listener<Inform> l) {
     236                listeners.add(l);
     237        }
     238
     239        @Override
     240        public void removeListener(Listener<Inform> l) {
     241                listeners.remove(l);
     242        }
     243
     244        /**
     245         * This should only be called by the owner of the listenable, not by
     246         * listeners or others. Avoid calling this from synchronized blocks as a
     247         * notified listener might immediately make more calls to you.
     248         * <p>
     249         * Any listeners that throw an exception will be intercepted and their
     250         * stacktrace is printed.
     251         *
     252         * @param data information about the change.
     253         */
     254        public void notifyListeners(Inform data) {
     255                for (Listener<Inform> l : listeners) {
     256                        l.notifyChange(data);
     257                }
     258        }
     259
    211260}
Note: See TracChangeset for help on using the changeset viewer.