Skip to content

Commit

Permalink
Merge remote-tracking branch 'phx/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaobin committed Jan 5, 2019
2 parents c3a7207 + 5286296 commit 7233efd
Show file tree
Hide file tree
Showing 73 changed files with 2,544 additions and 2,445 deletions.
110 changes: 6 additions & 104 deletions CHANGELOG.md
@@ -1,121 +1,23 @@
# Changelog for v1.4

See the [upgrade guides](https://gist.github.com/chrismccord/bb1f8b136f5a9e4abc0bfc07b832257e) to bring your Phoenix 1.3.x apps up to speed.
## New feature!

## Cowboy 2 support

TODO: Write about how to use Cowboy 2

## The Socket <-> Transport contract

We have used the opportunity of writing the new Cowboy 2 adapter to do an overhaul in how `Phoenix.Socket` interacts with transports. The result is a new API that makes it very easy to implement new transports and also allows developers to provide custom socket implementations without ceremony. For example, if you would like to have direct control of the socket and bypass the channel implementation completely, it is now very straight-forward to do so. See the `Phoenix.Socket.Transport` behaviour for more information.

This overhaul means that the `transport/3` macro in `Phoenix.Socket` is deprecated. Instead of defining transports in your socket.ex file:

transport :websocket, Phoenix.Transport.Websocket,
key1: value1, key2: value2, key3: value3

transport :longpoll, Phoenix.Transport.LongPoll,
key1: value1, key2: value2, key3: value3

Configurations must be applied directly in your endpoint file via the `Phoenix.Endpoint.socket/3` macro:

socket "/socket", MyApp.UserSocket,
websocket: [key1: value1, key2: value2, key3: value3],
longpoll: [key1: value1, key2: value2, key3: value3]

Note the websocket/longpoll configuration given to socket/3 will only apply after you remove all `transport/3` calls from your socket definition. If you have explicitly upgraded to Cowboy 2, any transport defined with the `transport/3` macro will be ignored.

The old APIs for building transports are also deprecated. The good news is: adapting an existing transport to the new API is a less error prone process where you should mostly remove code.


## 1.4.0-rc.4

### Enhancements
* [Endpoint] Allow custom keyword pairs to be passed to the socket `:connect_info` options.

## 1.4.0-rc.3 (2018-10-30)
## 1.5.0-dev

### Enhancements
* [phx.new] Update Ecto deps with the release of Ecto 3.0 including `phoenix_ecto` 4.0
* [phx.new] Import Ecto's `.formatter.exs` in new projects
* [Endpoint] Log the configured url instead of raw IP when booting endpoint webserver

## 1.4.0-rc.2 (2018-10-20)

### Enhancements

* [phx.new] Use Ecto 3.0RC, with `ecto_sql` in new project deps
* [phx.new] Use Plug 1.7 with new `:plug_cowboy` dependency for cowboy adapter
* [phx.gen.html|json|schema|context] Support new Ecto 3.0 usec datetime types
* [Endpoint] Allow named params to be used when defining socket paths

### Bug Fixes

* [Routes] Fix regression in router compilation failing to escape plug options
* [phx.gen.json|html] Fix generator tests incorrectly encoding datetimes
* [phx.gen.cert] Fix generation of cert inside umbrella projects

## 1.4.0-rc.1 (2018-10-12)

### Enhancements

* [Socket] Improve error message when missing socket mount in endpoint

### Bug Fixes

* Add missing `.formatter.exs` to hex package for proper elixir formatter integration
* [phx.gen.cert] Fix usage inside umbrella applications
* [phx.new] Revert `Routes.static_url` in app layout in favor of original `Routes.static_path`
* [phx.new] Use phoenix_live_reload 1.2-rc to fix hex version errors

### JavaScript client

* Fix reconnect caused by pending heartbeat

## 1.4.0-rc.0 (2018-10-09)

### Enhancements

* [ChannelTest] Respect user's configured ExUnit `:assert_receive_timeout` for macro assertions
* [Controller] Support partial file downloads with `:offset` and `:length` options to `send_download/3`
* [Controller] Add additional security headers to `put_secure_browser_headers` (`x-content-type-options`, `x-download-options`, and `x-permitted-cross-domain-policies`)
* [Controller] Add `put_router_url/2` to override the default URL generation pulled from endpoint configuration
* [Endpoint] Add `Cowboy2Adapter` for HTTP2 support with cowboy2
* [Endpoint] The `socket/3` macro now accepts direct configuration about websockets and longpoll
* [Endpoint] Support MFA function in `:check_origin` config for custom origin checking
* [Endpoint] Add new `:phoenix_error_render` instrumentation callback
* [Logger] Add whitelist support to `filter_parameters` logger configuration, via new `:keep` tuple format
* [Phoenix] Add `Phoenix.json_library/0` and replace `Poison` with `Jason` for JSON encoding in new projects
* [Router] Display list of available routes on debugger 404 error page
* [Router] Raise on duplicate plugs in `pipe_through` scopes
* [Presence] Add `Presence.get_by_key` to fetch presences for specific user
* [Socket] Add new `phoenix_socket_connect` instrumentation
* [Logger] Log calls to user socket connect
* [CodeReloader] Add `:reloadable_apps` endpoint configuration option to allow recompiling local dependencies

### Bug Fixes

* [Channel] Fix issue with WebSocket transport sending wrong ContentLength header with 403 response
* [Router] Fix forward aliases failing to expand within scope block

### Deprecations

* [Controller] Passing a view in `render/3` and `render/4` is deprecated in favor of `put_view/2`
* [Endpoint] The `:handler` option in the endpoint is deprecated in favor of `:adapter`
* [Socket] `transport/3` is deprecated. The transport is now specified in the endpoint
* [Transport] The transport system has seen an overhaul and been drastically simplified. The previous mechanism for building transports is still supported but it is deprecated. Please see `Phoenix.Socket.Transport` for more information

### phx.new installer

* Generate new Elixir 1.5+ child spec (therefore new apps require Elixir v1.5)
* Use webpack for asset bundling

### JavaScript client

* Add new instance-based Presence API with simplified synchronization callbacks
* Accept a function for socket and channel `params` for dynamic parameter generation when connecting and joining
* Fix race condition when presence diff arrives before state
* Fix `window` reference causing phoenix.js errors in environments without global window object.

## v1.3
## v1.4

The CHANGELOG for v1.3 releases can be found [in the v1.3 branch](https://github.com/phoenixframework/phoenix/blob/v1.3/CHANGELOG.md).
The CHANGELOG for v1.4 releases can be found [in the v1.4 branch](https://github.com/phoenixframework/phoenix/blob/v1.4/CHANGELOG.md).
15 changes: 6 additions & 9 deletions RELEASE.md
Expand Up @@ -6,15 +6,12 @@
2. Bump version in related files below
3. Update `phoenix_dep` in `installer/lib/phoenix_new.ex` and `installer/lib/phx_new/generator.ex` to "~> version to be released"
4. Run tests, commit, push code
5. Publish packages and docs after pruning any extraneous uncommitted files
6. Run `MIX_ENV=prod mix archive.build` and `MIX_ENV=prod mix archive.build -o phx_new.ez` inside "installer" directory to build new installers
7. Copy new installers to "phoenixframework/archives" project
8. Test installer by generating a new app, running `mix deps.get`, and compiling
9. Start -dev version in related files below
10. Update `phoenix_dep` in `installer/lib/phoenix_new.ex` back to git
11. Publish to `npm` with `npm publish`
12. Replace `master` for `source_url_pattern` in `installer/mix.exs`
13. Push installer (phx_new hex package) to hex
5. Publish `phx_new` and `phoenix` packages and docs after pruning any extraneous uncommitted files
6. Test installer by generating a new app, running `mix deps.get`, and compiling
7. Start -dev version in related files below
8. Update `phoenix_dep` in `installer/lib/phoenix_new.ex` back to git
9. Publish to `npm` with `npm publish`
10. Replace `master` for `source_url_pattern` in `installer/mix.exs`

## Files with version

Expand Down
39 changes: 32 additions & 7 deletions assets/js/phoenix.js
Expand Up @@ -185,7 +185,9 @@
* @module phoenix
*/

const global = typeof self !== "undefined" ? self : window
const globalSelf = typeof self !== "undefined" ? self : null
const globalWindow = typeof window !== "undefined" ? window : null
const global = globalSelf || globalWindow || this
const VSN = "2.0.0"
const SOCKET_STATES = {connecting: 0, open: 1, closing: 2, closed: 3}
const DEFAULT_TIMEOUT = 10000
Expand Down Expand Up @@ -421,7 +423,7 @@ export class Channel {
*/
join(timeout = this.timeout){
if(this.joinedOnce){
throw(`tried to join multiple times. 'join' can only be called a single time per channel instance`)
throw new Error(`tried to join multiple times. 'join' can only be called a single time per channel instance`)
} else {
this.joinedOnce = true
this.rejoin(timeout)
Expand Down Expand Up @@ -491,7 +493,7 @@ export class Channel {
*/
push(event, payload, timeout = this.timeout){
if(!this.joinedOnce){
throw(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`)
throw new Error(`tried to push '${event}' to '${this.topic}' before joining. Use channel.join() before pushing events`)
}
let pushEvent = new Push(this, event, function(){ return payload }, timeout)
if(this.canPush()){
Expand Down Expand Up @@ -593,7 +595,7 @@ export class Channel {
*/
trigger(event, payload, ref, joinRef){
let handledPayload = this.onMessage(event, payload, ref, joinRef)
if(payload && !handledPayload){ throw("channel onMessage callbacks must return the payload, modified or unmodified") }
if(payload && !handledPayload){ throw new Error("channel onMessage callbacks must return the payload, modified or unmodified") }

for (let i = 0; i < this.bindings.length; i++) {
const bind = this.bindings[i]
Expand Down Expand Up @@ -838,6 +840,7 @@ export class Socket {
this.flushSendBuffer()
this.reconnectTimer.reset()
this.resetHeartbeat()
this.resetChannelTimers()
this.stateChangeCallbacks.open.forEach( callback => callback() )
}

Expand Down Expand Up @@ -986,6 +989,15 @@ export class Socket {
}
})
}

/**
* @private
*/
resetChannelTimers() {
this.channels.forEach(channel => {
channel.rejoinTimer.restart()
})
}
}


Expand Down Expand Up @@ -1055,7 +1067,7 @@ export class LongPoll {
this.onerror()
this.closeAndRetry()
break
default: throw(`unhandled poll status ${status}`)
default: throw new Error(`unhandled poll status ${status}`)
}
})
}
Expand Down Expand Up @@ -1346,18 +1358,31 @@ class Timer {

reset(){
this.tries = 0
clearTimeout(this.timer)
this.clearTimer()
}

restart(){
const processing = this.timer !== null
this.reset()
if (processing){
this.scheduleTimeout()
}
}

/**
* Cancels any previous scheduleTimeout and schedules callback
*/
scheduleTimeout(){
clearTimeout(this.timer)
this.clearTimer()

this.timer = setTimeout(() => {
this.tries = this.tries + 1
this.callback()
}, this.timerCalc(this.tries + 1))
}

clearTimer() {
clearTimeout(this.timer)
this.timer = null
}
}

0 comments on commit 7233efd

Please sign in to comment.