Changeset 16


Ignore:
Timestamp:
06/22/20 16:08:10 (4 years ago)
Author:
bart
Message:

Tries harder to kill parties after deadline

Files:
12 added
4 edited

Legend:

Unmodified
Added
Removed
  • pom.xml

    r14 r16  
    66        <artifactId>partiesserver</artifactId>
    77        <packaging>war</packaging>
    8         <version>1.4.1</version> <!-- must equal ${geniusweb.version} -->
     8        <version>1.4.2</version> <!-- must equal ${geniusweb.version} -->
    99        <name>partiesserver Maven Webapp</name>
    1010        <url>http://maven.apache.org</url>
  • src/main/java/geniusweb/partiesserver/RunningPartiesUpdater.java

    r4 r16  
    1212 *
    1313 * This object keeps the {@link RunningPartiesRepo} up to date. Main job is to
    14  * remove parties that have been timed out. When a party times out,
    15  * it calls {@link Party#terminate()} but that might fail to stop a party.
    16  * In the end, the protocol should close the connection after the deadline. Start and run only once.
     14 * remove parties that have been timed out. When a party times out, it calls
     15 * {@link Party#terminate()} but that might fail to stop a party. In the end,
     16 * the protocol should close the connection after the deadline. Start and run
     17 * only once.
    1718 */
    1819public class RunningPartiesUpdater implements Runnable {
     
    2324         * when a negotiation runs out of time, the protocol may want to inform all
    2425         * parties about the failed session. If the parties are all killed at that
    25          * moment, this is impossible. Therefore we wait KILL_DELAY extra time before
    26          * really killing the parties.
     26         * moment, this is impossible. Therefore we wait KILL_DELAY extra time
     27         * before really killing the parties.
    2728         */
    2829        private static final long KILL_DELAY = 2000;
     
    3132         * @param repo   the {@link RunningPartiesRepo} that must be updated
    3233         *               automatically
    33          * @param period the period with which to check time-out (ms). Recommended 1000.
    34          *               After constructing you can run this in separate thread or just
    35          *               call {@link #run()}
     34         * @param period the period with which to check time-out (ms). Recommended
     35         *               1000. After constructing you can run this in separate
     36         *               thread or just call {@link #run()}
    3637         *
    3738         */
     
    5354                        }
    5455                } catch (InterruptedException e) {
    55                         System.err.println("ERROR:  RunningPartiesUpdater was interrupted!");
     56                        System.err
     57                                        .println("ERROR:  RunningPartiesUpdater was interrupted!");
    5658                }
    5759        }
    5860
    5961        /**
    60          * Called when some file that may be relevant has changed. Synchronized to avoid
    61          * weird states if filesystem changes rapidly. We ignore everything but jar
    62          * files.
     62         * Removes parties when they ran out of time. Called when some file that may
     63         * be relevant has changed, and periodically every {@link #period}.
     64         * Synchronized to avoid weird states if filesystem changes rapidly. We
     65         * ignore everything but jar files.
    6366         */
    6467        void update() {
     
    6669                        long now = System.currentTimeMillis();
    6770                        if (now >= party.getEndDate().getTime() + KILL_DELAY) {
     71                                log.log(Level.WARNING,
     72                                                "party " + party.getID() + " still running "
     73                                                                + KILL_DELAY / 1000
     74                                                                + "s after deadline. Removed now.");
    6875                                running.remove(party.getID());
    69                                 log.log(Level.WARNING, "party " + party.getID() + " still running 2s after deadline. Removed now.");
     76                                try {
     77                                        Thread.sleep(20);
     78                                } catch (InterruptedException e) {
     79                                }
    7080                        }
    7181                }
  • src/main/java/geniusweb/partiesserver/websocket/PartySocket.java

    r9 r16  
    4444public class PartySocket implements ConnectionEnd<Inform, Action> {
    4545        private final static ObjectMapper jackson = new ObjectMapper();
     46        private static final int MAX_MESSAGE_SIZE = 20 * 1024 * 1024;
     47
    4648        private final Reporter log;
    4749        private final RunningPartiesRepo runningparties;
    4850        private final List<Listener<Inform>> listeners = new CopyOnWriteArrayList<Listener<Inform>>();
    49         private static final int MAX_MESSAGE_SIZE = 20 * 1024 * 1024;
     51        private final ActiveThreads threads;
    5052
    5153        // should all be final, except that we can only set them when start is
     
    6668                this.runningparties = parties;
    6769                this.log = reporter;
     70                this.threads = new ActiveThreads(log);
    6871        }
    6972
     
    128131                        throw new IllegalStateException("Unexpected change of session ID");
    129132                }
     133                if (!threads.isEmpty()) {
     134                        log.log(Level.WARNING, "Party " + partyID
     135                                        + " is still busy with previous message");
     136                }
    130137                Inform info = jackson.readValue(informmessage, Inform.class);
    131138                RunningParty party = runningparties.get(partyID);
     
    135142                        log.log(Level.FINE, "Inform " + partyID + ": " + info);
    136143                        try {
     144                                threads.add();
    137145                                party.inform(info);
     146                                threads.remove();
    138147                        } catch (Throwable e) {
    139                                 log.log(Level.WARNING, "Party failed on inform.", e);
    140                                 e.printStackTrace();
    141                                 // severe as someone wants to debug that. Not severe for us
    142                                 // we don't use jackson.writeValueAsString(e) here because
    143                                 // CloseReason has 123 char limit.
    144                                 // The error will be too large to fit and will be truncated
    145                                 // therefore we send a plain string and hope that enough
    146                                 // will arrive at the other side (the protocol)
     148                                threads.remove();
     149                                if (e instanceof ThreadDeath)
     150                                        /*
     151                                         * ThreadDeath always prints stacktrace anwyay, stacktrace
     152                                         * is useless because it contains the thrower's stacktrace
     153                                         * instead of a useful message.
     154                                         */
     155                                        log.log(Level.WARNING,
     156                                                        "Party was killed while handling inform.");
     157                                else
     158                                        log.log(Level.WARNING, "Party failed on inform.", e);
     159                                /*
     160                                 * severe as someone wants to debug that. Not severe for us we
     161                                 * don't use jackson.writeValueAsString(e) here because
     162                                 * CloseReason has 123 char limit. The error will be too large
     163                                 * to fit and will be truncated therefore we send a plain string
     164                                 * and hope that enough will arrive at the other side (the
     165                                 * protocol)
     166                                 */
    147167                                session.close(new CloseReason(
    148168                                                CloseReason.CloseCodes.CLOSED_ABNORMALLY,
     
    186206        public void onClose() throws IOException {
    187207                log.log(Level.INFO, "socket closed to " + partyID);
    188                 /*
    189                  * for now just kill the party. Maybe we can do something with reconnect
    190                  * but that will be complex.
    191                  */
     208                if (!threads.isEmpty()) {
     209                        log.log(Level.WARNING, "Party " + partyID
     210                                        + " failed to terminate. Trying to kill the remaining threads.");
     211                        threads.killall();
     212                }
    192213                runningparties.remove(partyID);
    193214                outstream.stop();
  • src/test/java/geniusweb/partiesserver/JavaClientTest.java

    r14 r16  
    3939 */
    4040public class JavaClientTest {
    41         private static final String RANDOMPARTY = "http://localhost:8080/partiesserver/run/randomparty-1.4.1";
     41        private static final String RANDOMPARTY = "http://localhost:8080/partiesserver/run/randomparty-1.4.2";
    4242        // private static final String JSON = "{\"jobs\":[\"jobs1\"]}";
    4343//      private static final String JOBS1PROFILE = "{\"LinearAdditiveUtilitySpace\":{\"issueUtilities\":{\"lease car\":{\"discreteutils\":{\"valueUtilities\":{\"no\":0,\"yes\":1}}},\"permanent contract\":{\"discreteutils\":{\"valueUtilities\":{\"no\":0,\"yes\":1}}},\"career development opportunities\":{\"discreteutils\":{\"valueUtilities\":{\"high\":1,\"low\":0,\"medium\":0.5}}},\"fte\":{\"discreteutils\":{\"valueUtilities\":{\"1.0\":0.75,\"0.6\":0.25,\"0.8\":0.5}}},\"salary\":{\"discreteutils\":{\"valueUtilities\":{\"4000\":1.0,\"2500\":0.25,\"3500\":0.75,\"2000\":0,\"3000\":0.3}}},\"work from home\":{\"discreteutils\":{\"valueUtilities\":{\"1\":0.5,\"2\":0.666666666666,\"0\":0.333333333}}}},\"issueWeights\":{\"lease car\":0.06,\"permanent contract\":0.16,\"career development opportunities\":0.04,\"fte\":0.32,\"salary\":0.24,\"work from home\":0.18},\"domain\":{\"name\":\"jobs\",\"issuesValues\":{\"lease car\":{\"values\":[\"yes\",\"no\"]},\"permanent contract\":{\"values\":[\"yes\",\"no\"]},\"career development opportunities\":{\"values\":[\"low\",\"medium\",\"high\"]},\"fte\":{\"values\":[\"0.6\",\"0.8\",\"1.0\"]},\"salary\":{\"values\":[\"2000\",\"2500\",\"3000\",\"3500\",\"4000\"]},\"work from home\":{\"values\":[\"0\",\"1\",\"2\"]}}},\"name\":\"jobs1\"}}";
Note: See TracChangeset for help on using the changeset viewer.